先來(lái)看一個(gè)正常的例子:
package main
import (
"encoding/json"
"fmt"
)
type Student struct {
Name string
Id int
}
func main() {
s := Student{
Name:"chenchao",
Id:123,
}
buf, err := json.Marshal(s)
if err != nil{
fmt.Println(err)
}
fmt.Println(string(buf))
}
結(jié)果:
{"Name":"chenchao","Id":123}
再來(lái)看一個(gè)異常的例子:
我們將結(jié)構(gòu)體中的“Name”改寫為“name”再看結(jié)果
package main
import (
"encoding/json"
"fmt"
)
type Student struct {
name string
Id int
}
func main() {
s := Student{
name:"chenchao",
Id:123,
}
buf, err := json.Marshal(s)
if err != nil{
fmt.Println(err)
}
fmt.Println(string(buf))
}
結(jié)果:
{"Id":123}
會(huì)發(fā)現(xiàn)json后的數(shù)據(jù)Name不見了。
原因:
在go語(yǔ)言中的小寫開頭的變量或者函數(shù)為私有的,只限于當(dāng)前文件可見。但是json方法所在位置處在其它包中。所以在json時(shí)小寫的name是不能被發(fā)現(xiàn)的。這樣可以做到選擇性的序列化數(shù)據(jù)。
解決
第一種:
將小寫的name改為Name
但破壞了數(shù)據(jù)可見性
第二種:
package main
import (
"encoding/json"
"fmt"
)
type Student struct {
name string
Id int
}
// 在執(zhí)行json Marshal之前會(huì)先執(zhí)行此處的方法
func (s *Student)MarshalJSON() ([]byte, error) {
type JsonStudent struct {
Name string
Id int
}
w := JsonStudent{Name:s.name, Id:s.Id}
return json.Marshal(w)
}
func (s *Student) UnmarshalJSON(buf []byte) error {
// 這里專門處理json后的數(shù)據(jù)
type JsonStudent struct {
Name string
Id int
}
w := JsonStudent{Name:s.name, Id:s.Id}
return json.Unmarshal(buf, &w)
}
func main() {
s := &Student{
name:"chenchao",
Id:123,
}
buf, err := json.Marshal(s)
if err != nil{
fmt.Println(err)
}
fmt.Println("json dumps ",string(buf))
// unmarshal
_ =json.Unmarshal(buf, s) // 參數(shù)分別為 json數(shù)據(jù) 相對(duì)的數(shù)據(jù)變量
fmt.Println("json.load", s)
}
再來(lái)看一個(gè)相對(duì)復(fù)雜的例子:
package main
import (
"encoding/json"
"fmt"
)
var classroom = make(map[string]*Classroom)
type Classroom struct {
students map[string]*Student
}
type Student struct {
Name string
Id int
}
func (s *Classroom) MarshalJSON() ([]byte, error) {
//m := make(map[string]interface{})
//m["students"] = s.students
return json.Marshal(s.students)
}
func (s *Classroom) UnmarshalJSON(buf []byte) error {
cc := json.Unmarshal(buf, &s.students)
return cc
}
func main() {
s1 := Student{Name:"chenchao", Id:123}
s2 := Student{Name:"zhangsan", Id:234}
st := make(map[string]*Student)
st["chenchao"] = &s1
st["zhangsan"] = &s2
class1 := Classroom{
students: st,
}
classroom["class1"] = &class1
buf, err := json.Marshal(classroom)
if err != nil{
fmt.Println(err)
}
fmt.Println(string(buf))
err = json.Unmarshal(buf, &classroom)
if err !=nil {
fmt.Println("json load err: ", err)
}
for k,v := range classroom{
fmt.Println(k)
for s,t := range v.students{
fmt.Println(s, t)
}
}
}