json标签
type Author struct {
Name string `json:"name,omitempty"`
Age int32 `json:"age,string,omitempty"`
}
常见的两个标签是 string 和 omitempty,前者表示当前的整数或者浮点数是由 JSON 中的字符串表示的,而另一个字段 omitempty 会在字段为零值时,直接在生成的 JSON 中忽略对应的键值对,例如:“age”: 0、“author”: “” 等。标准库会使用 encoding/json.parseTag 函数来解析标签:
生成json
Marshal函数处理go的结构体
package main
import (
"encoding/json"
"os"
)
type ServerInfo struct {
//标签有string,ServerName的值会进行二次JSON编码 “”
ServerName string `json:"serverName"`
//ServerName2 string `json:"server_name_2,string"`
//如果ServerIP为空,则不输出到JSON中
ServerIP string `json:"serverIP,omitempty"`
}
type Server struct {
//ID不会导出到JSON
ID int `json:"-"`
ServerInfos []ServerInfo `json:"server_infos"`
Description string `json:"description,string"`
//tag中带有“,string”选项,在输出到JSON的时候会把该字段对应的值转换成JSON字符串
Score float32 `json:"score,string"`
}
func main(){
s01 := ServerInfo{
ServerName: "s1",
ServerIP: "10.0.12.1",
}
s02 := ServerInfo{
ServerName: "s2",
ServerIP: "",
}
s := Server{
ID: 3,
Description: `描述信息`,
Score: 87.2,
}
s.ServerInfos = append(s.ServerInfos, s01,s02)
b, _ := json.Marshal(s)
os.Stdout.Write(b)
}
得到json字符串
{"server_infos":[{"serverName":"s1","serverIP":"10.0.12.1"},{"serverName":"s2"}],"description":"\"描述信息\"","score":"87.2"}
解析json
json里含数字时,如果直接用json.Unmarshal解析,会默认将数据转为float64,可能会丢失精度
1.已知json结构体组成
以下读取方法,不会丢失数字精度
type ServerInfo struct {
//标签有string,ServerName的值会进行二次JSON编码 “”
ServerName string `json:"serverName"`
//ServerName2 string `json:"server_name_2,string"`
//如果ServerIP为空,则不输出到JSON中
ServerIP string `json:"serverIP,omitempty"`
}
type Server struct {
//ID不会导出到JSON
ID int `json:"-"`
ServerInfos []ServerInfo `json:"server_infos"`
Description string `json:"description,string"`
//tag中带有“,string”选项,在输出到JSON的时候会把该字段对应的值转换成JSON字符串
Score float32 `json:"score,string"`
Age int `json:"age"`
}
var s2 Server
decoder := json.NewDecoder(bytes.NewReader(b))
decoder.UseNumber()
err := decoder.Decode(&s2)
if err != nil {
fmt.Printf("json.Unmarshal failed, err:%v\n", err)
return
}
fmt.Println(s2)
fmt.Println(s2.Age,s2.Score)
fmt.Println(reflect.TypeOf(s2.Age),reflect.TypeOf(s2.Score))
2.未知json数据结构
decoder := json.NewDecoder(bytes.NewReader(b))
decoder.UseNumber()
s2 := make(map[string]interface{})
err := decoder.Decode(&s2)
if err != nil {
fmt.Printf("json.Unmarshal failed, err:%v\n", err)
return
}
fmt.Println(s2)
fmt.Println(s2["age"],s2["score"])
//打印结果:25 87.2
fmt.Println(reflect.TypeOf(s2["age"]),reflect.TypeOf(s2["age"]))
//打印类型:json.Number json.Number
3.自推断类型(推荐)
data := `{"server_infos":[{"serverName":"s1","serverIP":"10.0.12.1"},{"serverName":"s2"}],"description":"\"描述信息\"","score":"87.2","age":25}`
var tmp map[string]interface{}
json.Unmarshal([]byte(data), &tmp)
description := GetItemString(tmp,"description")
fmt.Println(description)
fmt.Println(reflect.TypeOf(description))
score := GetItemString(tmp,"score")
fmt.Println(score)
fmt.Println(reflect.TypeOf(score))
age := GetItemFloat64(tmp,"age")
fmt.Println(age)
fmt.Println(reflect.TypeOf(age))
//繁琐解析法
//fmt.Println(len(tmp["server_infos"].([]interface {})))
//mapTmp1 := (tmp["server_infos"].([]interface {}))[0].
// (map[string]interface {})
//fmt.Println(mapTmp1["serverName"])
//fmt.Println(mapTmp1["serverIP"])
//函数封装解析
server_infos := GetItemArray(tmp,"server_infos")
fmt.Println(server_infos)
fmt.Println(reflect.TypeOf(server_infos[0]))
serverName := GetItemString(server_infos[0].(map[string]interface{}),"serverName")
fmt.Println(serverName)
serverIP := GetItemString(server_infos[0].(map[string]interface{}),"serverIP")
fmt.Println(serverIP)
data1 := `{"data":{"t1":"sdd","t2":"sdsd","t3":{"y1":"sd","y2":"12"}}}`
json.Unmarshal([]byte(data1), &tmp)
test := GetItemMap(tmp,"data")
fmt.Println(test)
//fmt.Println(reflect.TypeOf(test))
t3 := GetItemMap(test,"t3")
fmt.Println(GetItemString(t3,"y2"))
//fmt.Println(reflect.TypeOf(t3))
//函数
func GetItemArray(parent map[string]interface{}, key string) []interface{} {
val, ok := parent[key].([]interface{})
if ok {
return val
} else {
return nil
}
}
func GetItemMap(parent map[string]interface{}, key string) map[string]interface{} {
val, ok := parent[key].(map[string]interface{})
if ok {
return val
} else {
return nil
}
}
func GetItemString(parent map[string]interface{}, key string) string {
val, ok := parent[key].(string)
if ok {
return val
}
return ""
}
func GetItemFloat64(parent map[string]interface{}, key string) float64 {
val, ok := parent[key].(float64)
if ok {
return val
}
return 0
}