packagemain
import(
"encoding/json"
"fmt"
//目前bitly公司开源了一个叫做simplejson的包,在处理未知结构体的JSON时相当方便:https://github.com/bitly/go-simplejson
"github.com/bitly/go-simplejson"//gogetgithub.com/bitly/go-simplejson
)
typeserverstruct{
ServerNamestring//如不想到处这个字段,ServerName首字母小写即可
ServerIPstring
}
typeserverliststruct{
Servers[]server
}
//例如JSON的key是Foo,那么怎么找对应的字段呢?
//首先查找tag含有Foo的可导出的struct字段(首字母大写)
//其次查找字段名是Foo的导出字段
//最后查找类似FOO或者FoO这样的除了首字母之外其他大小写不敏感的导出字段
/*解析到结构体:我们知晓被解析的JSON数据的结构的前提下采取的方案*/
funcmainstruct(){
vars serverlist
str:=`{"servers":[{"serverName":"Shanghai_VPN","serverIP":"127.0.0.1"},{"serverName":"Beijing_VPN","serverIP":"127.0.0.2"}]}`
json.Unmarshal([]byte(str),&s)
fmt.Println(s)
}
/*解析到结构体:我们不知道被解析的数据的格式*/
//官方提供的通过interface{}配合断言的方式来解析
/*Go类型和JSON类型的对应关系如下:
bool代表JSONbooleans,
float64代表JSONnumbers,
string代表JSONstrings,
nil代表JSONnull.*/
funcmainassert(){
b:=[]byte(`{"Name":"Wednesday","Age":6,"Parents":["Gomez","Morticia"]}`)
varf interface{}
err:=json.Unmarshal(b,&f)
iferr !=nil{
fmt.Printf("error%v",err)
}
fmt.Println(f)
m:=f.(map[string]interface{})
fork,v :=rangem {
switchvv :=v.(type){
casestring:
fmt.Println(k,"isstring",vv)
caseint:
fmt.Println(k,"isint",vv)
casefloat64:
fmt.Println(k,"isfloat64",vv)
case[]interface{}:
fmt.Println(k,"isanarray:")
fori,u :=rangevv {
fmt.Println(i,u)
}
default:
fmt.Println(k,"isofatypeIdon'tknowhowtohandle")
}
}
}
//simplejson
funcmainsimplejson(){
js,_ :=simplejson.NewJson([]byte(`{
"test":{
"array":[1,"2",3],
"int":10,
"float":5.150,
"bignum":9223372036854775807,
"string":"simplejson",
"bool":true
}
}`))
arr,_ :=js.Get("test").Get("array").Array()
fmt.Println(arr)
i,_ :=js.Get("test").Get("int").Int()
fmt.Println(i)
ms:=js.Get("test").Get("string").MustString()
fmt.Println(ms)
fmt.Println(js.Get("test").Get("bool").MustBool())
}
//生成json
typeServerstruct{
ServerNamestring`json:"serverName"`//必须通过structtag定义来实现key值的重命名
ServerIPstring`json:"serverIp"`
}
typeServerslicestruct{
Servers[]Server`json:"servers"`
}
//Marshal函数只有在转换成功的时候才会返回数据,在转换的过程中我们需要注意几点:
/*JSON对象只支持string作为key,所以要编码一个map,那么必须是map[string]T这种类型(T是Go语言中任意的类型)
Channel,complex和function是不能被编码成JSON的
嵌套的数据是不能编码的,不然会让JSON编码进入死循环
指针在编码的时候会输出指针指向的内容,而空指针会输出null*/
funcmain(){
vars Serverslice
s.Servers=append(s.Servers,Server{ServerName:"Shanghai_VPN",ServerIP:"127.0.0.1"})
s.Servers=append(s.Servers,Server{ServerName:"Beijing_VPN",ServerIP:"127.0.0.2"})
b,err :=json.Marshal(s)
iferr !=nil{
fmt.Println("jsonerr:",err)
}
fmt.Println(string(b))
}
//总结
/*针对JSON的输出,我们在定义structtag的时候需要注意的几点是:
字段的tag是"-",那么这个字段不会输出到JSON
tag中带有自定义名称,那么这个自定义名称会出现在JSON的字段名中,例如上面例子中serverName
tag中如果带有"omitempty"选项,那么如果该字段值为空,就不会输出到JSON串中
如果字段类型是bool,string,int,int64等,而tag中带有",string"选项,那么这个字段在输出到JSON的时候会把该字段对应的值转换成JSON字符串*/
//eg:
/*typeServerstruct{
//ID不会导出到JSON中
IDint`json:"-"`
//ServerName2的值会进行二次JSON编码
ServerNamestring`json:"serverName"`
ServerName2string`json:"serverName2,string"`
//如果ServerIP为空,则不输出到JSON串中
ServerIPstring`json:"serverIP,omitempty"`
}
s:=Server{
ID:3,
ServerName:`Go"1.0"`,
ServerName2:`Go"1.0"`,
ServerIP:``,
}
b,_:=json.Marshal(s)
os.Stdout.Write(b)
会输出以下内容:
{"serverName":"Go\"1.0\"","serverName2":"\"Go\\\"1.0\\\"\""}
*/