In Go language encoding/json The library provides complex functions to convert various types in Go to JSON format. We mainly use the following functions:
- Serialize a slice, structure or dictionary into a JSON format string [byte stream].
- Deserialize a JSON format string [byte stream] into a slice, structure or dictionary.
serialize
Serialization uses the Marshal function in the json Library:
func Marshal(v interface{}) ([]byte, error)
1. Structure serialization
For example, use the following structure to represent a movie:
type Movie struct { Title string Year int `json:"released"` Color bool `json:"color,omitempty"` Actors []string }
The strings json:"released" and json: "color, integrity" followed by the type in the definition are called field tags, which tell the json library some rules during serialization:
- json:"released" makes the corresponding name after serialization "released" instead of "Year".
- JSON: "Color, omitty" makes it ignored and not serialized if the value of the Color member is false.
Some rules for serialization without field tags:
- If the name of a structure member does not start with an uppercase letter, it is not serialized.
- If the name of a structure member starts with an uppercase letter, the serialized name is the member name.
The code for serialization is as follows:
movie := Movie{ Title: "Casablanca", Year: 1942, Color: false, Actors: []string{"Humphrey Bogart", "Ingrid Bergman"}, } data, err := json.Marshal(movie) if err != nil { log.Fatalf("JSON marshaling failed: %s", err) } fmt.Printf("%s\n", data)
Output:
{"Title":"Casablanca","released":1942,"Actors":["Humphrey Bogart","Ingrid Bergman"]}
2. Dictionary serialization
To serialize a dictionary into JSON format, its key must be a string.
Here is an example:
info := map[string]int{ "width": 1280, "height": 720, } data, err := json.MarshalIndent(info, "", " ") if err != nil { log.Fatalf("JSON marshaling failed: %s", err) } fmt.Printf("%s\n", data)
Output:
{ "height": 720, "width": 1280 }
Here, we use the MarshalIndent function to make the output JSON format easier to read. The serialized name is the name of the key in the dictionary.
3. Slice serialization
Look directly at an example:
type Movie struct { Title string Year int `json:"released"` Color bool `json:"color,omitempty"` Actors []string } var movies = []Movie{ { Title: "Casablanca", Year: 1942, Color: false, Actors: []string{"Humphrey Bogart", "Ingrid Bergman"}, }, { Title: "Cool Hand Luke", Year: 1967, Color: true, Actors: []string{"Paul Newman"}, }, { Title: "Bullitt", Year: 1968, Color: true, Actors: []string{"Steve McQueen", "Jacqueline Bisset"}, }, } data, err := json.MarshalIndent(movies, "", " ") if err != nil { log.Fatalf("JSON marshaling failed: %s", err) } fmt.Printf("%s\n", data)
Output:
[ { "Title": "Casablanca", "released": 1942, "Actors": [ "Humphrey Bogart", "Ingrid Bergman" ] }, { "Title": "Cool Hand Luke", "released": 1967, "color": true, "Actors": [ "Paul Newman" ] }, { "Title": "Bullitt", "released": 1968, "color": true, "Actors": [ "Steve McQueen", "Jacqueline Bisset" ] } ]
Deserialization
Deserialization uses the Unmarshal function:
func Unmarshal(data []byte, v interface{}) error
1. Clearly know JSON format
We will first express the JSON format as a definite type.
1. The following JSON format:
{ "name": "Awesome 4K", "resolutions": [ { "width": 1280, "height": 720 }, { "width": 1920, "height": 1080 }, { "width": 3840, "height": 2160 } ] }
To deserialize it into a Go object, we can represent it with the following structure:
struct { Name string Resolutions []struct { Width int Height int } }
2. The following JSON format represents resolution information:
{ "height": 720, "width": 1280 }
You can also use map[string]int, that is, dictionary to represent:
3. The following JSON format:
[ { "width": 1280, "height": 720 }, { "width": 1920, "height": 1080 }, { "width": 3840, "height": 2160 } ]
Represented by slice [] map[string]int.
In any case, a certain JSON format can always be represented by a tangent, structure, or dictionary.
Then you can deserialize:
var jsonBlob = []byte(` [ { "width": 1280, "height": 720 }, { "width": 1920, "height": 1080, }, { "width": 3840, "height": 2160 } ] `) di := []map[string]int{} err = json.Unmarshal(jsonBlob, &di) if err != nil { fmt.Println("error:", err) } fmt.Printf("%+v\n", di)
output
[map[height:720 width:1280] map[height:1080 width:1920] map[height:2160 width:3840]]
2. Unable to determine JSON format
The format that cannot be determined can be directly represented by the interface {} type. At this time, if it is a json object, the json library will use the map[string]interface {} type to represent it during deserialization. If it is a json array, it will use the [] interface {} type to represent it. Type assertion is required for the specific type corresponding to the specific interface {}.
See an example:
package main import ( "encoding/json" "fmt" ) func main() { var jsonBlob = []byte(` { "name": "Awesome 4K", "price": 1999.9, "resolutions": [ { "width": 1280, "height": 720 }, { "width": 1920, "height": 1080 }, { "width": 3840, "height": 2160 } ] } `) var d interface{} err := json.Unmarshal(jsonBlob, &d) if err != nil { fmt.Println("error:", err) } fmt.Println(d) m := d.(map[string]interface{}) for k, v := range m { switch vv := v.(type) { case string: fmt.Println(k, "is string", vv) case float64: fmt.Println(k, "is float64", vv) case []interface{}: fmt.Println(k, "is an 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") } } }