在Go语言中使用JSON 叁歲伎倆 2022-06-11 00:12 181阅读 0赞 ## Encode ## 将一个对象编码成JSON数据,接受一个interface\{\}对象,返回\[\]byte和error: func Marshal(v interface{ }) ([]byte, error) Marshal函数将会递归遍历整个对象,依次按成员类型对这个对象进行编码,类型转换规则如下: bool类型 转换为JSON的Boolean 整数,浮点数等数值类型 转换为JSON的Number string 转换为JSON的字符串(带""引号) struct 转换为JSON的Object,再根据各个成员的类型递归打包 数组或切片 转换为JSON的Array []byte 会先进行base64编码然后转换为JSON字符串 map 转换为JSON的Object,key必须是string interface{} 按照内部的实际类型进行转换 nil 转为JSON的null channel,func等类型 会返回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 ## 将JSON数据解码 func Unmarshal(data []byte, v interface{}) error 类型转换规则和上面的规则类似 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}] ## 结构体 ## 结构体必须是**大写字母开头**的成员才会被JSON处理到,**小写字母开头**的成员不会有影响。 Mashal时,结构体的成员变量名将会直接作为JSON Object的key打包成JSON;Unmashal时,会自动匹配对应的变量名进行赋值。 **Unmarshal时,如果JSON中有多余的字段,会被直接抛弃掉;如果JSON缺少某个字段,则直接忽略不对结构体中变量赋值,不会报错。** 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\n", m) var s Message err := json.Unmarshal(b, &s) if err != nil { fmt.Printf(err.Error()) return } fmt.Printf("%+v", s) Output: {Bob Hello 1294706395881547000 ok} {Name:Bob Body: Time:0 inner:} ## StructTag ## 如果希望手动配置结构体的成员和JSON字段的对应关系,可以在定义结构体的时候给**成员打标签**: 使用`omitempty`,如果该字段为nil或0值(数字0,字符串”“,空数组\[\]等),则打包的JSON结果不会有这个字段。 type Message struct { Name string `json:"msg_name"` // 对应JSON的msg_name Body string `json:"body,omitempty"` // 如果为空置则忽略字段 Time int64 `json:"-"` // 直接忽略字段 } 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"} ## 更灵活地使用JSON ## 使用json.RawMessage json.RawMessage其实就是\[\]byte类型的重定义。可以进行强制类型转换。 现在有这么一种场景,结构体中的其中一个字段的格式是未知的: type Command struct { ID int Cmd string Args *json.RawMessage } 使用json.RawMessage的话,Args字段在Unmarshal时不会被解析,直接将字节数据赋值给Args。我们可以能先解包第一层的JSON数据,然后根据Cmd的值,再确定Args的具体类型进行第二次Unmarshal。 这里要注意的是,一定要使用指针类型\*json.RawMessage,否则在Args会被认为是\[\]byte类型,在打包时会被打包成base64编码的字符串。 type Color struct { ID int `json:"_ID"` Name string `json:"_NAME"` Colors []string `json:"_Colors,omitempty"` I json.RawMessage `json:"_test"` } bb := []byte(`{ "_ID":2,"_NAME":"R","_Colors":["red","ruby"],"_test":{ "a":"aa","b":"bb"}}`) var g Color err1 := json.Unmarshal(bb, &g) if err1 != nil { fmt.Println("error:", err1) } fmt.Printf("%+v\n", g) var t map[string]string err := json.Unmarshal(g.I, &t) if err != nil { fmt.Println("error:", err) } fmt.Println(t) output: {ID:2 Name:R Colors:[red ruby] I:[123 34 97 34 58 34 97 97 34 44 34 98 34 58 34 98 98 34 125]} map[b:bb a:aa] ## 使用interface\{\} ## interface\{\}类型在Unmarshal时,会自动将JSON转换为对应的数据类型: JSON的boolean 转换为bool JSON的数值 转换为float64 JSON的字符串 转换为string JSON的Array 转换为[]interface{} JSON的Object 转换为map[string]interface{} JSON的null 转换为nil 需要注意的有两个。一个是所有的JSON数值自动转换为float64类型,使用时需要再手动转换为需要的int,int64等类型。第二个是JSON的object自动转换为map\[string\]interface\{\}类型,访问时直接用JSON Object的字段名作为key进行访问。再不知道JSON数据的格式时,可以使用interface\{\}。 **interface\{\}接收任何类型** ## 自定义类型 ## 如果希望自己定义对象的打包解包方式,可以实现以下的接口: type Marshaler interface { MarshalJSON() ([]byte, error) } type Unmarshaler interface { UnmarshalJSON([]byte) error } 实现该接口的对象需要将自己的数据打包和解包。如果实现了该接口,json在打包解包时则会调用自定义的方法,不再对该对象进行其他处理。 func main() { var strjson = `{ "isok":1,"name":"polaris"}` var model = struct { Name string `json:"name"` IsOk intbool `json:"isok"` }{} err := json.Unmarshal([]byte(strjson), &model) if err != nil { fmt.Println(err) return } fmt.Println(model.IsOk, model.Name) } type intbool bool func (this *intbool) UnmarshalJSON(data []byte) error { if "1" == string(data) { *this = intbool(true) } else { *this = intbool(false) } return nil } output: true polaris 参考:[http://blog.csdn.net/tiaotiaoyly/article/details/38942311][http_blog.csdn.net_tiaotiaoyly_article_details_38942311] [http_blog.csdn.net_tiaotiaoyly_article_details_38942311]: http://blog.csdn.net/tiaotiaoyly/article/details/38942311
还没有评论,来说两句吧...