type Person struct { ID uint Name string Age int } funcMarshalPerson() { p := Person{ ID: 1, Name: "Bruce", Age: 18, } output, err := json.Marshal(p) if err != nil { panic(err) } println(string(output)) } funcUnmarshalPerson() { str := `{"ID":1,"Name":"Bruce","Age":18}` var p Person err := json.Unmarshal([]byte(str), &p) if err != nil { panic(err) } fmt.Printf("%+v\n", p) }
// The structure used here is the same as the previous one, // so I won't repeat it. error is also not captured to save space.
func MarshalPerson() { p := Person{ ID: 1, Name: "Bruce", address: address{ Code: 100, Street: "Main St", }, } // It would be more pretty by MarshalIndent output, _ := json.MarshalIndent(p, "", " ") println(string(output)) } func UnmarshalPerson() { str := `{"ID":1,"Name":"Bruce","address":{"Code":100,"Street":"Main St"}}` var p Person _ = json.Unmarshal([]byte(str), &p) fmt.Printf("%+v\n", p) } // Output MarshalPerson: { "ID": 1, "Name": "Bruce", "Code": 100, "Street": "Main St" } // Ouptput UnmarshalPerson: {ID:1 Name:Bruce address:{Code:0 Street:}}
这里先声明一个 Person 对象,然后使用 MarshalIndent 美化序列化结果并打印出来。从打印输出中我们可以看到,整个 Person 对象都被扁平化了。就 Person 结构而言,尽管进行了组合,但它看起来仍有一个地址成员字段。因此,有时我们会想当然地认为 Person 的序列化 JSON 看起来是这样的:
1 2 3 4 5 6 7 8 9
// The imagine of JSON serialization result { "ID": 1, "Name": "Bruce", "address": { "Code": 100, "Street": "Main St" } }
但事实并非如此,它被扁平化了。这更符合我们之前直接通过 Person 访问地址成员时的感觉,即地址成员似乎直接成为了 Person 的成员。这一点需要注意,因为这种组合会使序列化后的 JSON 结果扁平化。
// PartUpdateIssue simulates parsing two different // JSON strings with the same structure func PartUpdateIssue() { var p Person // The first data has the ID field and is not 0 str := `{"ID":1,"Name":"Bruce"}` _ = json.Unmarshal([]byte(str), &p) fmt.Printf("%+v\n", p) // The second data does not have an ID field, // deserializing it again with p preserves the last value str = `{"Name":"Jim"}` _ = json.Unmarshal([]byte(str), &p) // Notice the output ID is still 1 fmt.Printf("%+v\n", p) } // Output {ID:1 Name:Bruce} {ID:1 Name:Jim}
许多开发人员一听到指针这个词就头疼不已,其实大可不必。但 Go 中的指针确实给开发人员带来了 Go 程序中最常见的 panic 之一:空指针异常。当指针与 JSON 结合时会发生什么呢?
看下面的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
type Person struct { ID uint Name string Address *Address }
func UnmarshalPtr() { str := `{"ID":1,"Name":"Bruce"}` var p Person _ = json.Unmarshal([]byte(str), &p) fmt.Printf("%+v\n", p) // It would panic this line // fmt.Printf("%+v\n", p.Address.Street) } // Output {ID:1 Name:Bruce Address:<nil>}