Go如何实现json字符串与各类struct相互转换

Go如何实现json字符串与各类struct相互转换

目录

json字符串与各类struct相互转换

简单总结

结构体转换为JSON字符串的一个坑

来看一下这个例子

json字符串与各类struct相互转换

不废话了都在代码中了

package main import ( "fmt" "reflect" "encoding/json" "strings" ) type Class struct { Grade int `json:"grade"` //年级 ClassNumber int `json:"classNumber"` //班级号 } type Student struct{ Name string //大写开头,可被导出,没有`json:".."`,导出json的字段名是原本名称 age int //小写开题,不可被导出 Hight int `json:"currentHight"` //导出对应json的字段名为currentHight Class *Class `class` //指针,指向引用对象;如果不用指针,只是值复制 } func doMarshal(){//对象转json字符串 nClass:=new(Class)//new只给给特定类型分配内存,设置“零”值,返回其地址(指针) fmt.Printf("nClass的类型是%s,内容是%v\n",reflect.TypeOf(nClass),*nClass) nClass.Grade=3 nClass.ClassNumber=6 nStudents:=make([]*Student,0) //make只用于map,slice和channel,并且不显示返回指针 //这个切片,存放Student的指针 nStudent:=Student{"Lily",7,116,nClass} jsonBytes,err1:=json.Marshal(nStudent)//解析后的是[]byte if err1!=nil{ fmt.Printf("转json失败:%v\n",err1) return } fmt.Println("转成的JSON:") //age不会被导出 //{"Name":"Lily","currentHight":116,"Class":{"grade":3,"classNumber":6}} fmt.Println(string(jsonBytes)) nStudents=append(nStudents,&Student{"Lilei",8,130,nClass}) nStudents=append(nStudents,&nStudent) josnListBytes,err2:=json.Marshal(nStudents) if err2!=nil{ fmt.Printf("转jsonList失败:%v\n",err2) return } fmt.Println("转成的列表型JSON:") fmt.Println(string(josnListBytes)) //[{"Name":"Lilei","currentHight":130,"Class":{"grade":3,"classNumber":6}},{"Name":"Lily","currentHight":116,"Class":{"grade":3,"classNumber":6}}] } func doUnMarshal(){//json字符串转对象 jsonStr:=` { "Name":"Lily", "currentHight":116, "age":12, "Class":{ "grade":3, "classNumber":6 }, "score":[98,100,95] } ` jsonListStr:=`[ { "Name":"Lucy", "currentHight":120, "Class":{ "grade":3, "classNumber":5 } }, { "Name":"Lily", "currentHight":116, "Class":{ "grade":3, "classNumber":6 } } ]` //第一种解析json方式,解析到Struct/[]Struct student:=Student{}//同new(Student) err:=json.Unmarshal([]byte(jsonStr),&student) //Unmarshall第2个参数必须是指针,否则报错:json: Unmarshal(non-pointer main.Student) //因为必须解析到具体的对象,所以需传入对象引用,而不是值传递 //score在Student中没有此字段,所以被忽略了 if err!=nil{ fmt.Printf("解析json字符串异常:%s\n",err) } fmt.Printf("学生的名称是%v,班级信息是%v,年龄是%v(私有对象不能导入,初始为0)\n",student.Name,*student.Class,student.age) //学生的名称是Lily,学生的班级信息是{3 6},学生的年龄是0 students:=[]*Student{} //定义切片,同make([]*Student,0) err=json.Unmarshal([]byte(jsonListStr),&students) if err!=nil{ fmt.Printf("解析json字符串异常:%s\n",err) } for _,stu:=range students{ //这里stu是指针类型,获取其属性可以直接用.Name,也可以解引用后用.Name fmt.Printf("列表:学生的名称是%s,身高是%d,在%d年级%d班\n",stu.Name,(*stu).Hight,(*stu.Class).Grade,stu.Class.ClassNumber) } //第二种解析到interface{}/[]interface{} fmt.Println("*************解析json*************") var student1 interface{} err=json.Unmarshal([]byte(jsonStr),&student1) if err!=nil{ fmt.Printf("解析json字符串异常:%s\n",err) } c:=-1 resolve2JosnObj(student1,c) /* *************解析json************* map元素: map[Name]的元素: 类型是string,值是 Lily map[currentHight]的元素: 类型float64,值是 116 map[age]的元素: 类型float64,值是 12 map[Class]的元素: map元素: ---map[classNumber]的元素: 类型float64,值是 6 ---map[grade]的元素: 类型float64,值是 3 map[score]的元素: list元素: ---第0个元素: 类型float64,值是 98 ---第1个元素: 类型float64,值是 100 ---第2个元素: 类型float64,值是 95 */ fmt.Println("*************解析jsonlist*************") var students1 interface{} err=json.Unmarshal([]byte(jsonListStr),&students1) if err!=nil{ fmt.Printf("解析jsonlist字符串异常:%s\n",err) } d:=-1 resolve2JosnObj(students1,d) /* *************解析jsonlist************* list元素: 第0个元素: map元素: ---map[Name]的元素: 类型是string,值是 Lucy ---map[currentHight]的元素: 类型float64,值是 120 ---map[Class]的元素: map元素: ------map[grade]的元素: 类型float64,值是 3 ------map[classNumber]的元素: 类型float64,值是 5 第1个元素: map元素: ---map[Class]的元素: map元素: ------map[grade]的元素: 类型float64,值是 3 ------map[classNumber]的元素: 类型float64,值是 6 ---map[Name]的元素: 类型是string,值是 Lily ---map[currentHight]的元素: 类型float64,值是 116 */ } func resolve2JosnObj(objI interface{},c int){ c=c+1 switch obj:=objI.(type) { //此处[interface{}].(type) 专门用于switch的类型判断 case string: fmt.Println("类型是string,值是",obj) case float64: fmt.Println("类型float64,值是",obj) case map[string]interface{}: fmt.Println("map元素:") for k,vi:=range obj{ fmt.Printf("%smap[%s]的元素: ",strings.Repeat("---",c),k) resolve2JosnObj(vi,c) } case []interface{}: fmt.Println("list元素:") for i,vi:=range obj{ fmt.Printf("%s第%d个元素: ",strings.Repeat("---",c),i) resolve2JosnObj(vi,c) } default: fmt.Println("无法判断类型,类型是",reflect.TypeOf(obj),"值是",obj) } } func main() { doMarshal()//对象转json字符串 doUnMarshal() } 简单总结

1、结构体对象可生成json字符串,Marshal()是[]byte,需要string去转换

2、json字符串可以映射到一个struct,但仅限公共元素(大写开头);也可通用的转换到空接口interfece[],使用对应转换到需要的内容

结构体转换为JSON字符串的一个坑

通过json.Marshal来将结构体数据转换为json字符串时,需要注意结构体内成员变量的首字母大小写的问题,很容易会掉进坑里.

来看一下这个例子 package main import ( "encoding/json" "fmt" ) type Student struct { Name string age int } func main() { var s Student = Student { Name: "xiaomo", age: 18, } fmt.Printf("%+v\n", s) res, _ := json.Marshal(s) fmt.Println(string(res)) }

运行输出如下:

$ go run test_json.go
{Name:xiaomo age:18}
{"Name":"xiaomo"}

可以看到转换的json字符串中只包含了Name字段,age字段被忽略了.这是由于在进行json解析时,只会转换结构体能够导出的字段(首字母大写),其他字段将会被忽略.

这个机制也有个好处,可以根据实际需要,将想要导出字段的名字首字母大写,其他字段首字母小写隐藏起来即可.

以上为个人经验,希望能给大家一个参考,也希望大家多多支持易知道(ezd.cc)。

推荐阅读

    电脑硬盘csgo凭空消失|csgo突然消失

    电脑硬盘csgo凭空消失|csgo突然消失,,1. csgo突然消失可能是系统出现卡顿,刷新一下重启试试2. csgo地图突然消失方法如下:1、在电脑中启动cs

    csgo参数设置|csgo怎么保存

    csgo参数设置|csgo怎么保存,,csgo怎么保存第一步下载csgo的官方版本。然后再下载一个5e对战平台,PS:5e的账号和csgo的账号不是一个账号。第

    aigo无线硬盘连电脑|aigo优盘连接手机

    aigo无线硬盘连电脑|aigo优盘连接手机,,1. aigo优盘连接手机不管是爱国者U盘还是其他的U盘,要导入华为手机的话,首先需要有一个转接头,一头插

    csgo高手快捷键|csgo快捷键指令

    csgo高手快捷键|csgo快捷键指令,,1. csgo快捷键指令反恐精英全球攻势游戏中,死亡竞赛的回合时间60分钟:mp_roundtime 60,休闲/竞技模式的每局

    aigo电脑主机系统重启|csgo重启电脑

    aigo电脑主机系统重启|csgo重启电脑,,csgo重启电脑如果重启成功应该是不需要,相反就需重新安装csgo重启电脑重连不上直接打开游戏,通过游戏

    csgo电脑等级|csgo电脑等级指令

    csgo电脑等级|csgo电脑等级指令,,csgo电脑等级指令如图:竞技匹配等级另外还有每打一局都加经验的那个等级是满级为40,满了之后可兑换赛季纪

    csgo设置准星|csgo设置准星大小

    csgo设置准星|csgo设置准星大小,,csgo设置准星大小csgo怎么设置准星方法:1.打开CSGO游戏,打开创意工坊,查找crashz' Crosshair Generator v2

    duolingo电脑版|Duolingo软件

    duolingo电脑版|Duolingo软件,,Duolingo软件1.百词斩:2.英语流利说:“英语流利说”是一款融合创新口语教学理念和尖端语音评估技术的英语口