The method of using JSON in the Go language


Encode

Encode 1 object as JSON data, accept 1 interface{} object, return []byte and error:

func Marshal(v interface{}) ([]byte, error)

The Marshal function recursively traverses the entire object and encodes the object in turn according to its member type. The conversion rules are as follows:

bool type is converted to Boolean of JSON Integer, floating point, and other numeric types are converted to Number of JSON string converted to JSON (with "" quotes) struct is converted to Object of JSON and is recursively packaged according to the type of each member Array for array or slice conversion to JSON []byte encodes base64 and converts it to an JSON string map converts to Object of JSON, key must be string interface{} is converted according to the actual type inside nil to null of JSON channel,func, and others return UnsupportedTypeError

type ColorGroup struct {
 ID  int
 Name string
 Colors []string
}
group := ColorGroup{
 ID:  1,
 Name: "Reds",
 Colors: []string{"Crimson", "Red", "Ruby", "Maroon"},
}
b, err := json.Marshal(group)
if err != nil {
 fmt.Println("error:", err)
}
os.Stdout.Write(b)
Output:
{"ID":1,"Name":"Reds","Colors":["Crimson","Red","Ruby","Maroon"]}

Decode

Decode the JSON data

func Unmarshal(data []byte, v interface{}) error

The type conversion rules are similar to those above

var jsonBlob = []byte(`[
 {"Name": "Platypus", "Order": "Monotremata"},
 {"Name": "Quoll", "Order": "Dasyuromorphia"}
]`)
type Animal struct {
 Name string
 Order string
}
var animals []Animal
err := json.Unmarshal(jsonBlob, &animals)
if err != nil {
 fmt.Println("error:", err)
}
fmt.Printf("%+v", animals)
Output:
[{Name:Platypus Order:Monotremata} {Name:Quoll Order:Dasyuromorphia}]

The structure of the body

To be processed by JSON, the structure must be a member beginning with an uppercase letter. Members beginning with a lowercase letter are not affected.

When Mashal, the member variable name of the structure will be packaged as JSON of JSON Object directly. Unmashal will automatically match the corresponding variable name for assignment, case insensitive.

In Unmarshal, if there are redundant fields in JSON, they will be discarded directly. If JSON is missing a field, it simply ignores not assigning a variable to the structure and does not report an error.

type Message struct {
 Name string
 Body string
 Time int64
 inner string
}
var m = Message{
 Name: "Alice",
 Body: "Hello",
 Time: 1294706395881547000,
 inner: "ok",
}
b := []byte(`{"nAmE":"Bob","Food":"Pickle", "inner":"changed"}`)
err := json.Unmarshal(b, &m)
if err != nil {
 fmt.Printf(err.Error())
 return
}
fmt.Printf("%v", m)
Output:
{Bob Hello 1294706395881547000 ok}

StructTag

If you want to manually configure the members of the structure to correspond to the JSON field, you can label the members when defining the structure:

Familiar with omitempty, if the field is nil or has a value of 0 (the number 0, string "", empty array [], etc.), then the packaged JSON result does not have this field.

type Message struct {
 Name string `json:"msg_name"`  //  The corresponding JSON the msg_name
 Body string `json:"body,omitempty"` //  Ignore the field if it is empty
 Time int64 `json:"-"`    //  Just ignore the field
}
var m = Message{
 Name: "Alice",
 Body: "",
 Time: 1294706395881547000,
}
data, err := json.Marshal(m)
if err != nil {
 fmt.Printf(err.Error())
 return
}
fmt.Println(string(data))
Output:
{"msg_name":"Alice"}

Be more flexible with JSON

Using json RawMessage

json.RawMessage is essentially a redefinition of the []byte type. Casts can be performed.

Here is a scenario in which the format of one of the fields in the structure is unknown:

type Command struct {
 ID int
 Cmd string
 Args *json.RawMessage
}

With ES109en.RawMessage, the Args field is not parsed at Unmarshal, and the byte data is assigned to Args. We can unpack the JSON data of the first layer, and then determine the specific type of Args for the second time according to the value of Cmd.

Note here that 1 must use pointer type * json.RawMessage, otherwise Args would be considered a []byte type and would be packaged as an base64-encoded string when packaged.

Use interface {}

When type interface{} is in Unmarshal, it will automatically convert JSON to the corresponding data type:

JSON the boolean  convert bool
JSON The numerical   convert float64
JSON The string   convert string
JSON the Array  convert []interface{}
JSON the Object  convert map[string]interface{}

null converted to nil

There are two things to note. One is that all JSON values are automatically converted to float64 type, which needs to be manually converted to int, int64 type. The second is that object of JSON is automatically converted to map[string]interface{} type and accessed directly using the field name of JSON Object as key. When you no longer know the format of JSON data, you can use interface{}.

Custom type

If you want to define your own way to package and unpackage objects, you can implement the following interface:

type Marshaler interface {
 MarshalJSON() ([]byte, error)
}
type Unmarshaler interface {
 UnmarshalJSON([]byte) error
}

Objects that implement this interface need to package and unpackage their own data. If the interface is implemented, json calls the custom method when it is packaged and unpacked, with no further processing on the object.

conclusion