先来看一个正常的例子:
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))
}
结果:
{"Name":"chenchao","Id":123}
再来看一个异常的例子:
我们将结构体中的“Name”改写为“name”再看结果
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))
}
结果:
{"Id":123}
会发现json后的数据Name不见了。
原因:
在go语言中的小写开头的变量或者函数为私有的,只限于当前文件可见。但是json方法所在位置处在其它包中。所以在json时小写的name是不能被发现的。这样可以做到选择性的序列化数据。
解决
第一种:
将小写的name改为Name
但破坏了数据可见性
第二种:
package main
import (
"encoding/json"
"fmt"
)
type Student struct {
name string
Id int
}
// 在执行json Marshal之前会先执行此处的方法
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后的数据
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) // 参数分别为 json数据 相对的数据变量
fmt.Println("json.load", s)
}
再来看一个相对复杂的例子:
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)
}
}
}