This is a creation in Article, where the information may have evolved or changed.
JSON (JavaScript Object Notation) is a lightweight data exchange language that is text-based, self-descriptive and easy to read. Although JSON is a subset of JavaScript, JSON is a language-independent text format and uses some of the same habits as the C language family. The biggest difference between JSON and XML is that XML is a complete markup language, and JSON is not. JSON is smaller, faster, easier to parse than XML, and the browser's built-in fast parsing support makes it more suitable for network data transmission. We now see a lot of open platforms that are basically using JSON as their interface for data interaction. Since JSON is so important in web development, how does the go language support JSON? The standard library of the Go language has been very well supported by JSON, which makes it easy to encode and decode JSON data.
Examples of operations in the previous section are expressed in JSON, and the results are described as follows:
{"Servers": [{"ServerName": "Shanghai_vpn", "ServerIP": "127.0.0.1"},{"ServerName": "Beijing_vpn", "ServerIP": " 127.0.0.2 "}]}
The remainder of this section will be based on this JSON data to introduce the JSON packet encoding and decoding of the Go language.
Parsing JSON
Parse to struct
If we had the JSON string above, how would we parse the JSON string? The JSON package for Go has the following function
Func unmarshal (data []byte, v interface{}) error
Through this function we can achieve the purpose of the analysis, the detailed analysis of examples, see the following code:
Package Mainimport ( "Encoding/json" " fmt") type Server struct { ServerName string serverip String}type serverslice struct { Servers []server}func Main () { var s serverslice str: = ' {"Servers": [{" ServerName ":" Shanghai_vpn "," ServerIP ":" 127.0.0.1 "},{" ServerName ":" Beijing_vpn "," ServerIP ":" 127.0.0.2 "}]} ' Json. Unmarshal ([]byte (str), &s) FMT. Println (s)}
In the example code above, we first defined the structure that corresponds to the JSON data, the array corresponds to the slice, the field name corresponds to the key in the JSON, how to match the JSON data with the struct field when parsing? For example JSON key is Foo , then how to find the corresponding field?
- First
Foo , look for the exportable struct fields that the tag contains (capitalize the first letter)
- Next find the field name is
Foo the export field
- Finally, look
FOO for an export field similar to or FoO less sensitive to case except the first letter.
Smart you must have noticed this: the field that can be assigned must be an exportable field (that is, the first letter capitalized). At the same time, the JSON parsing will only parse the fields that can be found, the missing fields will be ignored, one of the advantages is: When you receive a large JSON data structure and you just want to get some of the data, you just need to put the data you want to the field name in uppercase, you can easily solve the problem.
Parsing to interface
The above parsing method is the solution we know the structure of the parsed JSON data, if we do not know the format of the parsed data, and how to parse it?
We know that interface{} can be used to store objects of any data type, which is exactly the result of storing JSON data for an unknown structure that is parsed. The JSON package uses map[string]interface{} and the []interface{} structure to store any JSON objects and arrays. The corresponding relationship between the go type and the JSON type is as follows:
- The bool represents the JSON Booleans,
- Float64 represents the JSON numbers,
- String represents the JSON strings,
- Nil represents JSON null.
Now let's assume that the JSON data below
B: = []byte (' {' "Name": "Wednesday", "Age": 6, "parents": ["Gomez", "Morticia"]} ')
If we don't know his structure, we'll parse him into interface{}.
var f interface{}err: = json. Unmarshal (b, &f)
At this time f stored a map type, their key is a string, the value is stored in the empty interface{}
f = map[string]interface{}{ "Name": "Wednesday", "age": 6, "parents": []interface{}{ "Gomez", "Morticia", },}
So how do you get access to this data? By asserting the way:
M: = f. (map[string]interface{})
After the assertion, you can access the data in the following ways
For k, V: = range m { switch VV: = V. (type) {case string: fmt. Println (k, ' is String ', vv) case int: FMT. Println (K, "is Int.", VV) case float64: fmt. Println (K, "is Float64", vv) case []interface{}: fmt. Println (K, "is a array:") for I, u: = range VV { FMT. Println (i, u) } default: FMT. Println (K, "is of a type I don ' t know how to handle") }}
As you can see from the example above, we can parse the JSON number of the unknown structure by interface{} with the type Assert.
Above this is the official solution, in fact, many times we through the type assertion, the operation is not very convenient, the current bitly company Open source a simplejson package called, in the processing of the unknown structure of the JSON is very convenient, detailed examples are as follows:
JS, err: = Newjson ([]byte (' {" " test ": { " array ": [1," 2 ", 3], " int ": Ten, " float ": 5.150, " Bignum ": 9223372036854775807, "string": "Simplejson", "bool": True }} ')) arr, _: = js. Get ("Test"). Get ("array"). Array () I, _: = js. Get ("Test"). Get ("int"). Int () MS: = JS. Get ("Test"). Get ("string"). Muststring ()
As you can see, using this library to manipulate JSON is much simpler than the official package, please refer to the following address for details: Https://github.com/bitly/go-simplejson
Generate JSON
When we develop a lot of applications, the final thing is to output the JSON data string, so how to handle it? The JSON package Marshal is handled by functions, and the function is defined as follows:
Func Marshal (v interface{}) ([]byte, error)
Suppose we still need to generate the server list information above, then how to handle it? Take a look at the following example:
Package Mainimport ( "Encoding/json" " fmt") type Server struct { ServerName string serverip String}type serverslice struct { Servers []server}func Main () { var s serverslice s.servers = append (s). Servers, Server{servername: "Shanghai_vpn", ServerIP: "127.0.0.1"}) s.servers = append (S.servers, server{ ServerName: "Beijing_vpn", ServerIP: "127.0.0.2"}) B, err: = json. Marshal (s) if err! = Nil { FMT. PRINTLN ("JSON err:", err) } fmt. Println (string (b))}
The output is as follows:
{"Servers": [{"ServerName": "Shanghai_vpn", "ServerIP": "127.0.0.1"},{"ServerName": "Beijing_vpn", "ServerIP": " 127.0.0.2 "}]}
We see that the first letter of the output field name above is in uppercase, what if you want to use the lower case of the first letter? Change the field name of the struct to the first letter lowercase? JSON output must be noted that only the exported fields will be output, if you modify the field name, then you will find that nothing is output, so it must be implemented through the struct tag definition:
Type Server struct { ServerName string ' JSON: ' ServerName ' ' serverip string ' JSON: ' ServerIP ' '}type Serverslice struct { Servers []server ' JSON: ' Servers '}
By modifying the structure definition above, the JSON string of the output is consistent with the JSON string we defined at the very beginning.
For the output of JSON, we need to be aware of the following points when defining a struct tag:
- The field tag is
"-" , then this field is not output to the JSON
- Tag with a custom name, this custom name will appear in the JSON field name, for example in the example above servername
- If there is an option in the tag
"omitempty" , then if the field value is empty, it will not be exported to the JSON string
- If the field type is bool, string, int, int64, and so on, and the tag has an
",string" option, this field converts the value of the field to a JSON string when output to JSON
For example:
Type Server struct { //ID is not exported to JSON ID int ' JSON: "-" ' //ServerName value will be two times JSON encoded ServerName String ' JSON: ' ServerName ' ' ServerName2 string ' JSON: ' servername2,string ' //If ServerIP is empty, it is not output to the JSON string ServerIP string ' JSON: ' Serverip,omitempty ' '}s: = Server { ID: 3, ServerName: ' Go ' 1.0 "', ServerName2: ' Go ' 1.0 ', ServerIP: ",}b, _: = json. Marshal (s) os. Stdout.write (b)
Will output the following:
{"ServerName": "Go \" 1.0\ "", "serverName2": "\" Go \\\ "1.0\\\" \ "}
The marshal function only returns data when the conversion is successful, and we need to note several points during the conversion process:
- The JSON object only supports string as key, so to encode a map, it must be a type map[string]t (T is any type in the Go language)
- Channel, complex and function are not encoded as JSON.
- Nested data cannot be encoded, otherwise JSON encoding goes into a dead loop
- The pointer outputs the contents of the pointer as it is encoded, and the null pointer outputs null
In this section, we describe how to use the Go language's JSON standard package to encode and decode JSON data, as well as a brief introduction to using third-party packages go-simplejson to simplify operations in some cases, and learning to use them skillfully will be very important for our next Web development.