这个包可以实现json的编码和解码,就是将json字符串转换为struct
,或者将struct
转换为json。
核心的两个函数
编码函数 Marshal
func Marshal(v interface{}) ([]byte, error)
将 struct 或 map 编码成json,可以接收任意类型
结构体转换为json
package main
import (
"encoding/json"
"fmt")
type Person struct {
Name string
Age int
Email string
}
func Marsha() {
p := Person{
Name: "tom",
Age: 20,
Email: "[email protected]",
}
b, _ := json.Marshal(p)
fmt.Printf("b: %v\n", string(b))
}
func main() {
Marsha()
}
map 转换为json
package main
import (
"encoding/json"
"fmt")
type Person struct {
Name string
Age int
Email string
}
func Marsha() {
p := make(map[string]interface{}, 20)
p["名称"] = "张三"
p["性别"] = "男"
p["年龄"] = "18"
b, _ := json.Marshal(p)
fmt.Printf("b: %v\n", string(b))
}
func main() {
Marsha()
}
解码函数 Unmarshal
func Unmarshal(data []byte, v interface{}) error
将json转码成struct结构体 或是 map
此函数的关键点在与 v 的数据类型,但是建议还是使用 结构体作为 v 的类型,毕竟可以使用 tag 标签来更加精准的解析数据
特别注意:第二次参数必须传入地址,否则修改不成功
json 转 map
package main
import (
"encoding/json"
"fmt")
type Person struct {
Name string
Age int
Email string
}
func Marsha() []byte {
p := make(map[string]interface{}, 20)
p["名称"] = "张三"
p["性别"] = "男"
p["年龄"] = "18"
b, _ := json.Marshal(p)
return b
}
func Unmarshal(b []byte) {
var m map[string]interface{}
json.Unmarshal(b, &m)
fmt.Printf("%v\n", m)
}
func main() {
Unmarshal(Marsha())
}
json转换为结构体
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string
Age int
Gender string
}
func Marsha() []byte {
p := make(map[string]interface{}, 20)
p["name"] = "张三"
p["gender"] = "男"
p["age"] = "18"
b, _ := json.Marshal(p)
return b
}
func Unmarshal(b []byte) {
var m Person
json.Unmarshal(b, &m)
fmt.Printf("%v\n", m)
}
func main() {
Unmarshal(Marsha())
}
解析嵌套类型
package main
import (
"encoding/json"
"fmt"
)
type Parents []string
type Person struct {
Name string
Age int
Email string
Parents
}
// 解析嵌套类型
func Unmarshal() {
b := []byte(`{"Name":"tom","Age":20,"Email":"[email protected]", "Parents":["tom", "kite"]}`)
var f Person
json.Unmarshal(b, &f)
fmt.Printf("f: %v\n", f)
}
func main() {
Unmarshal()
}
忽略字段
如果你想在json 编码/解码 (序列化或反序列化)的时候忽略掉结构体中的某个字段,可以按如下方式在tag中添加-
。
如果你想在json序列化/反序列化的时候忽略掉结构体中的某个字段,可以按如下方式在tag中添加-
。
当然,如果你把变量名弄成小写,也是可以实现忽略的效果滴§( ̄▽ ̄)§
// 使用json tag指定json序列化与反序列化时的行为
type Person struct {
Name string `json:"name"` // 指定json序列化/反序列化时使用小写name
Age int64
Weight float64 `json:"-"` // 指定json序列化/反序列化时忽略此字段
}
忽略空值字段
当 struct 中的字段没有值时, json.Marshal()
序列化的时候不会忽略这些字段,而是默认输出字段的类型零值(例如int
和float
类型零值是 0,string
类型零值是""
,对象类型零值是 nil)。如果想要在序列序列化时忽略这些没有值的字段时,可以在对应字段添加omitempty
tag。
举个例子:
type User struct {
Name string `json:"name"`
Email string `json:"email"`
Hobby []string `json:"hobby"`
}
func omitemptyDemo() {
u1 := User{
Name: "七米",
}
// struct -> json string
b, err := json.Marshal(u1)
if err != nil {
fmt.Printf("json.Marshal failed, err:%v\n", err)
return
}
fmt.Printf("str:%s\n", b)
}
输出结果:
str:{"name":"七米","email":"","hobby":null}
如果想要在最终的序列化结果中去掉空值字段,可以像下面这样定义结构体:
// 在tag中添加omitempty忽略空值
// 注意这里 hobby,omitempty 合起来是json tag值,中间用英文逗号分隔
type User struct {
Name string `json:"name"`
Email string `json:"email,omitempty"`
Hobby []string `json:"hobby,omitempty"`
}
此时,再执行上述的omitemptyDemo
,输出结果如下:
str:{"name":"七米"} // 序列化结果中没有email和hobby字段
忽略嵌套结构体空值字段
首先来看几种结构体嵌套的示例:
type User struct {
Name string `json:"name"`
Email string `json:"email,omitempty"`
Hobby []string `json:"hobby,omitempty"`
Profile
}
type Profile struct {
Website string `json:"site"`
Slogan string `json:"slogan"`
}
func nestedStructDemo() {
u1 := User{
Name: "七米",
Hobby: []string{"足球", "双色球"},
}
b, err := json.Marshal(u1)
if err != nil {
fmt.Printf("json.Marshal failed, err:%v\n", err)
return
}
fmt.Printf("str:%s\n", b)
}
匿名嵌套Profile
时序列化后的json串为单层的:
str:{"name":"七米","hobby":["足球","双色球"],"site":"","slogan":""}
想要变成嵌套的json串,需要改为具名嵌套或定义字段tag:
type User struct {
Name string `json:"name"`
Email string `json:"email,omitempty"`
Hobby []string `json:"hobby,omitempty"`
Profile `json:"profile"`
}
// str:{"name":"七米","hobby":["足球","双色球"],"profile":{"site":"","slogan":""}}
想要在嵌套的结构体为空值时,忽略该字段,仅添加omitempty
是不够的:
type User struct {
Name string `json:"name"`
Email string `json:"email,omitempty"`
Hobby []string `json:"hobby,omitempty"`
Profile `json:"profile,omitempty"`
}
// str:{"name":"七米","hobby":["足球","双色球"],"profile":{"site":"","slogan":""}}
还需要使用嵌套的结构体指针:
type User struct {
Name string `json:"name"`
Email string `json:"email,omitempty"`
Hobby []string `json:"hobby,omitempty"`
*Profile `json:"profile,omitempty"`
}
// str:{"name":"七米","hobby":["足球","双色球"]}
不修改原结构体忽略空值字段
我们需要json序列化User
,但是不想把密码也序列化,又不想修改User
结构体,这个时候我们就可以使用创建另外一个结构体PublicUser
匿名嵌套原User
,同时指定Password
字段为匿名结构体指针类型,并添加omitempty
tag,示例代码如下:
type User struct {
Name string `json:"name"`
Password string `json:"password"`
}
type PublicUser struct {
*User // 匿名嵌套
Password *struct{} `json:"password,omitempty"`
}
func omitPasswordDemo() {
u1 := User{
Name: "七米",
Password: "123456",
}
b, err := json.Marshal(PublicUser{User: &u1})
if err != nil {
fmt.Printf("json.Marshal u1 failed, err:%v\n", err)
return
}
fmt.Printf("str:%s\n", b) // str:{"name":"七米"}
}