数据类型中转json的函数
基本数据转json
Marshal使用以下与类型相关的默认编码:
布尔值编码为JSON布尔值。
浮点数、整数和数字值编码为JSON数字。
字符串值编码为JSON字符串,强制为有效的UTF-8;
用Unicode替换符文替换无效字节。
这样JSON就可以安全地嵌入到HTML
map转JSON
type user struct {Username string `json:"name"`Userid string `json:"id"`Age int `json:"age"`
}func main() {jsonS()
}func jsonS() {//Go的标准包encoding/json对JSON的支持//JSON编码即将Go数据类型转换为JSON字符串m := make(map[string]interface{})m["name"] = "小花"m["age"] = 18u1 := user{Username: "小红",Userid: "1024",Age: 10,}marshal, err := json.Marshal(m)i, _ := json.Marshal(u1)fmt.Println(i)fmt.Println(string(i))if err != nil {fmt.Println(err.Error())return}fmt.Println(string(marshal))
}
运行结果:
结构体转json
注意:如果结构体中的字段以小写字母开头,那么结构体在抓换 json时不会解析该字段:
如果结构体转json时定义的结构体没有指定转换json时的字段别名,那么结构体转json后会按照结构体字段名显示
例如:
type DogW struct {Name stringAge intcolor string
}type CatC struct {name stringage intcolor string
}type HenH struct {Name string `json:"name"`Age int `json:"age"`Color string `json:"color"`
}func main() {d := DogW{Name: "汪汪",Age: 2,color: "黄",}c := CatC{name: "喵喵",age: 3,color: "狸花",}h := HenH{Name: "咯咯哒",Age: 1,Color: "黄红",}indent, err := json.MarshalIndent(d, "", "")if err != nil {fmt.Println("转换失败")return}fmt.Println("Dog结构体转json--", string(indent))marshalIndent, err := json.MarshalIndent(c, "", " ")fmt.Println("Cat结构体转json--", string(marshalIndent))i, err := json.MarshalIndent(h, "", "")fmt.Println("Hen结构体转json--", string(i))}
将json输出格式化,以便于阅读
u1 := user{Username: "小红",Userid: "1024",Age: 10,}
//将json输出 格式化
// MarshalIndent类似于Marshal,但使用缩进来格式化输出。//输出中的每个JSON元素将在以prefix开头的新行开始//根据缩进嵌套,后跟一个或多个缩进副本。indent, err := json.MarshalIndent(u1, "", " ")fmt.Println(string(indent))
结构体匿名字段转Json
type DogW struct {DName stringDAge intDColor stringCatC //匿名字段
}type CatC struct {Name stringAge intColor string
}func main() {d := DogW{DName: "汪汪",DAge: 2,DColor: "黄",CatC: CatC{Name: "喵喵",Age: 3,Color: "狸花",},}indent, err := json.MarshalIndent(d, "", "")if err != nil {fmt.Println("转换失败")return}fmt.Println("Dog结构体转json--", string(indent))}
注意:json包在解析匿名字段时,会将匿名字段的字段当成该结构体的字段处理
另外,如果嵌套的匿名字段的属性跟外部结构体的字段名一致,那么在转json后 只会显示外部的字段比如下面的代码:
type DogW struct {Name stringAge intColor stringCatC //匿名字段
}type CatC struct {Name stringAge intColor string
}func main() {d := DogW{Name: "汪汪",Age: 2,Color: "黄",CatC: CatC{Name: "喵喵",Age: 3,Color: "狸花",},}indent, err := json.MarshalIndent(d, "", "")if err != nil {fmt.Println("转换失败")return}fmt.Println("Dog结构体转json--", string(indent))
这里就有许多情况—下面的情况就很好玩
type DogW struct {Name stringAge intcolor stringCatC //匿名字段
}type CatC struct {Name stringAge intColor string
}func main() {d := DogW{Name: "汪汪",Age: 2,color: "黄",CatC: CatC{Name: "喵喵",Age: 3,Color: "狸花",},}
indent, err := json.MarshalIndent(d, "", "")if err != nil {fmt.Println("转换失败")return}fmt.Println("Dog结构体转json--", string(indent))
结果:
Marshal()函数源码
func Marshal(v any) ([]byte, error) {e := newEncodeState()defer encodeStatePool.Put(e)err := e.marshal(v, encOpts{escapeHTML: true})if err != nil {return nil, err}buf := append([]byte(nil), e.Bytes()...)return buf, nil
}
Marshal()函数只有在转换成功的时候才会返回数据,在转换的过程中需要注意如下几点。• JSON对象只支持string作为key,所以要编码一个map,必须是map[string]T这种类型(T是Go语言中的任意类型)。• channel、complex和function是不能被编码成JSON的。• 指针在编码的时候会输出指针指向的内容,而空指针会输出null。
json转Go中数据类型
//结构体
type CatC struct {Name string `json:"name"`Age int `json:"age"`Color string `json:"color"`
}//json解析
//JSON解析就是将JSON转换为Go数据类型。func UNJSON() {d := DogW{Name: "dog",Age: 2,color: "黄",CatC: CatC{Name: "喵喵",Age: 3,Color: "狸花",},}//转换成jsonindent, err := json.MarshalIndent(d, "", " ")if err != nil {return}fmt.Println(string(indent))var dog DogW//json转go类型err = json.Unmarshal(indent, &dog)fmt.Println(dog)data := `[{"level":"debug","Msg":"File:\"test.txt\"NOT FOUND"},` + `{"Level":"","msg":"Logic error"}]`Catc := `{"Name":"狸花猫","Age":2,"Color":"梨花"}`Catd := `{"name":"狸花猫","age":2,"color":"梨花"}`var mapM []map[string]stringjson.Unmarshal([]byte(data), &mapM)var catc CatCvar catd CatCjson.Unmarshal([]byte(Catc), &catc)json.Unmarshal([]byte(Catd), &catd)fmt.Println(mapM)fmt.Println(catc)fmt.Println(catd)
}func main() {UNJSON()
}
注意json.Unmarshal([]byte(data), &mapM)中第二个参数要取址才会将解析出来的数据赋值给 对象mapM
JSON可以转换成结构体。同编码一样,json包是通过反射机制来实现解码的,因此结构体必须导出所转换的字段,不导出的字段不会被json包解析。另外解析时不区分大小写。
json转结构体时也是支持json标签的:
结果如下:
{"Name": "dog","Age": 2,"name": "喵喵","age": 3,"color": "狸花"
}
{dog 2 {喵喵 3 狸花}}
[map[Msg:File:"test.txt"NOT FOUND level:debug] map[Level: msg:Logic error]]
{狸花猫 2 梨花}
{狸花猫 2 梨花}
如果在换转换时有匿名字段—>>
在解码JSON时,如果找不到字段,则查找字段的字段
比如下面的例子:
type CatCC struct {Name string `json:"name"`Age int `json:"age"`Color string `json:"color"`
}
type DogWW struct {DName stringDAge intDcolor stringCatCC //匿名字段
}func main() {//UNJSON()TestUnjson()
}func TestJson() {Dogw := `{"DName":"dogdog","DAge":22,"Dcolor":"Black","CatCC":{"Name":"喵miaomiao喵","Age":3,"Color":"狸花"}}`Dogww := `{"Name":"dogdog","Age":22,"color":"Red","CatCC":{"Name":"喵miaomiao喵","Age":3,"Color":"狸花"}}`var dog *DogWWvar dogw *DogWWjson.Unmarshal([]byte(Dogw), dog)json.Unmarshal([]byte(Dogww), dogw)fmt.Println(&dog)fmt.Println(&dogw)
}
运行结果:
结构体没有字段时,会使用结构体字段对应的类型默认值
这也体现了 结构体中嵌套了匿名结构体----继承
如果结构体属性中没有值,那么我们可以通过加入 json 字段来将空的值给忽略:
type User struct {Name string `json:"name"`Email string `json:"email"` //加上omitempty标签,表示输出会将空值忽略掉,此时暂不加,看结果Hobby []string `json:"hobby"`
}func omitemptyDemo1() {// 当 struct 中的字段没有值Email,Hobby 字段时us := User{Name: "Gavin",}b, err := json.Marshal(us)if err != nil {fmt.Printf("json.Marshal failed, err:%v\n", err)return}fmt.Printf("str:%s\n", b)
}
运行结果:
{"name":"Jack","email":"","hobby":null}
str:{"name":"Jack","email":"","hobby":null}
加入omitempty标签后:
type User struct {Name string `json:"name"`Email string `json:"email,omitempty"` //加上omitempty标签,表示输出会将空值忽略掉Hobby []string `json:"hobby,omitempty"`
}
//运行结果 str:{"name":"Jack"}
json转嵌套结构体
type Pig struct {PName string `json:"pname"`Age int `json:"age"`
}type Animals struct {Types stringGroup []Pig
}func main() {var r Animalss := `{"Types":"猪","Group":[{"pname":"大猪","age":3},{"pname":"小猪仔","age":1}]}`err := json.Unmarshal([]byte(s), &r)if err != nil {fmt.Print(err)}fmt.Println(r)
}