Dynamic JSON in the Go language

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed. The Go language is a static type language, although it can also show dynamic types, but using a nested ' map[string]interface{} ' where barking can make the code particularly ugly. By mastering the static nature of the language, we can do better. When exchanging a variety of information through the same channel, we often need JSON to have dynamic, or more appropriate, parameter content. First, let's talk about message encapsulation (msg envelopes), where JSON looks like this: "json{" type ":" This part tells the "what to interpret the message", "Ms G ": ... the actual message is here, in some kind of json ...} The ' # # # generates JSON through different message types through ' interface{} ', and we can easily encode the data structure into a separate encapsulated, JSON data with multiple types of message bodies. In order to generate the following JSON: "json{" type ":" Sound "," msg ": {" description ":" Dynamite "," authority ":" The Bruce Dickinson "}}" "JSON {"type": "Cowbell", "msg": {"more": True}} "" We can use these Go types: ' ' Gopackage mainimport ("Encoding/json" "FMT" "Log") type Envelope struct {Type stringmsg interface{}}type sound struct {Description stringauthority string}type cowbell struct {Mor e Bool}func Main () {s: = Envelope{type: "Sound", Msg:sound{description: "Dynamite", Authority: "The Bruce Dickinson",},}bu F, err: = json. Marshal (s) if err! = Nil {log. Fatal (Err)}fmt. Printf ("%s\n", buf) c: = Envelope{tyPE: "cowbell", msg:cowbell{more:true,},}buf, err = json. Marshal (c) if err! = Nil {log. Fatal (Err)}fmt. The result of Printf ("%s\n", BUF)} "' Output is: ' ' json{' Type ':" Sound "," MSG ": {" Description ":" Dynamite "," authority ":" The Bruce Dickinson "}}{" Type ":" Cowbell "," MSG ": {" more ": true}" "These are nothing special. # # Parsing JSON to dynamic type if you want to parse the above JSON object into an object of type ' Envelope ', eventually you will parse the ' Msg ' field into a ' map[string]interface{} '. This method is not very useful, will make you regret your choice. "' Gopackage mainimport (" Encoding/json "" FMT "" log ") const input = ' {' type ': ' Sound ', ' msg ': {' description ': ' Dynamite ', ' Authority ":" The Bruce Dickinson "}} ' type Envelope struct {type stringmsg interface{}}func main () {var env envelopeif err: = json. Unmarshal ([]byte (Input), &env); Err! = Nil {log. Fatal (ERR)}//for the love of Gopher does not do thisvar desc string = env.msg. (map[string]interface{}) ["description"]. (string) fmt. PRINTLN (DESC)} ' output: ' ' Dynamite ' # # Clear parsing way As previously said, I recommend modifying the ' Envelope ' type, just like this: ' Gotype Envelope {type stringmsg *json. Rawmessage} ' [' JSON. Rawmessage '] (http://golang.org/pkg/encoding/json/#RawMessage) is useful in that it allows you to delay parsing the corresponding JSON data. It stores the unhandled data as ' []byte '. This approach allows you to explicitly control the parsing of ' MSG '. This is deferred until the value of ' type ' is obtained, and is parsed according to the value of ' type '. The downside of this approach is that you need to explicitly parse ' msg ', or you need to separate ' envelopein ' and ' envelopeout ' two types, where ' envelopeout ' still has ' msg interface{} '. # # Combine ' *json. Rawmessage ' and ' interface{} ' advantages so how to combine the good side of the two above? By placing ' *json ' in the ' interface{} ' field. Rawmessage '! ' ' Gopackage mainimport ("Encoding/json" "FMT" "log") const input = ' {' type ': ' Sound ', ' msg ': {' description ': "Dynamite", "authority": "The Bruce Dickinson"}} ' type Envelope struct {type stringmsg interface{}}type sound struct {DESCR Iption stringauthority String}func Main () {var msg json. Rawmessageenv: = envelope{msg: &msg,}if err: = json. Unmarshal ([]byte (Input), &env); Err! = Nil {log. Fatal (ERR)}switch env. Type {case ' sound ': var s soundif err: = json. Unmarshal (msg, &s); Err! = Nil {log. Fatal (Err)}var desc string = S.DESCRIPTIONFMT.PRINTLN (desc) default:log. Fatalf ("Unknown message type:%q", env. Type)}} ' output: ' ' Dynamite ' # # How to put all the data on the outermost layer (Top level) Although I highly recommend that you put dynamic parts under a single key, sometimes you may need to work with some pre-existing data that is not formatted in this way. If you can, please use the style mentioned earlier in the article. "json{" type ":" This part tells the message ",... the actual message was here, as multiple keys ...} "We can solve this by parsing two of data." "' Gopackage mainimport (" Encoding/json "" FMT "" log ") const input = ' {' type ': ' Sound ', ' description ': ' Dynamite ', ' Authority ":" The Bruce Dickinson "} ' type Envelope struct {type string}type sound struct {Description stringauthority string }func Main () {var env envelopebuf: = []byte (input) If err: = json. Unmarshal (buf, &env); Err! = Nil {log. Fatal (ERR)}switch env. Type {case ' sound ': var s struct {envelopesound}if err: = json. Unmarshal (buf, &s); Err! = Nil {log. Fatal (Err)}var desc string = S.DESCRIPTIONFMT.PRINTLN (desc) default:log. Fatalf ("Unknown message type:%q", env. Type)}} "" "Dynamite"

via:http://eagain.net/articles/go-dynamic-json/

Author: Tommi Virtanen Translator: jliu666 proofreading: polaris1119

This article by GCTT original compilation, go language Chinese network honor launches

This article was originally translated by GCTT and the Go Language Chinese network. Also want to join the ranks of translators, for open source to do some of their own contribution? Welcome to join Gctt!
Translation work and translations are published only for the purpose of learning and communication, translation work in accordance with the provisions of the CC-BY-NC-SA agreement, if our work has violated your interests, please contact us promptly.
Welcome to the CC-BY-NC-SA agreement, please mark and keep the original/translation link and author/translator information in the text.
The article only represents the author's knowledge and views, if there are different points of view, please line up downstairs to spit groove

1036 Reads

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.