The method of using JSON in the Go language

  • 2020-06-15 09:12:53
  • OfStack

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


Related articles: