前言,最近项目中须要动态解析json字符串,可是golang标准库提供的json须要事先定义好结构体,不太灵活,所以须要调研不依赖于结构体的json库
以性能的高低排序: jsonparser > easyjson > encoding/json > go-simplejson, gabs, jasongit
性能测试, 可见jsonparser的github
buger/jsonparsergithub
golang标准库的json须要预先定义好结构体,而后才能将json字符串转化为golang的结构体;simplejson这个开源的库能够在不知道json字符串具体结构的状况下进行编码和解码golang
import ( simplejson "github.com/bitly/go-simplejson" ) func case1() { //初始化*simpleJson.Json对象 sj, err := simplejson.NewJson([]byte(jsonStr)) var v *simpleJson.Json //获取字段,若是有多级,能够层层嵌套获取 v = sj.Get(字段名1).Get(字段名2) //将v的值转化为具体类型的值,MustXXX方法必定能够转化成功 //若转化不成功,则转化为该类型的零值 result := v.MustString() } func case2() { //检查某个字段是否存在 _, ok := js.Get("字段名1").CheckGet("字段名2") if ok { fmt.Println("存在!") } else { fmt.Println("不存在") } }
虽然simplejson能够转化一个未知的json,但想要获取到具体的值,仍然须要知道它的类型,这样最后一步转换才能成功json
import "github.com/buger/jsonparser" ... data := []byte(`{ "person": { "name": { "first": "Leonid", "last": "Bugaev", "fullName": "Leonid Bugaev" }, "github": { "handle": "buger", "followers": 109 }, "avatars": [ { "url": "https://avatars1.githubusercontent.com/u/14009?v=3&s=460", "type": "thumbnail" } ] }, "company": { "name": "Acme" } }`) //根据层级关系取特定的字段名对应的值 jsonparser.Get(data, "person", "name", "fullName") //若是知道须要取的目标字段的值的类型,能够使用详细的GetXXX方法 jsonparser.GetInt(data, "person", "github", "followers") // When you try to get object, it will return you []byte slice pointer to data containing it // In `company` it will be `{"name": "Acme"}` jsonparser.Get(data, "company") // If the key doesn't exist it will throw an error var size int64 if value, err := jsonparser.GetInt(data, "company", "size"); err == nil { size = value } // You can use `ArrayEach` helper to iterate items [item1, item2 .... itemN] jsonparser.ArrayEach(data, func(value []byte, dataType jsonparser.ValueType, offset int, err error) { fmt.Println(jsonparser.Get(value, "url")) }, "person", "avatars") // Or use can access fields by index! jsonparser.GetInt("person", "avatars", "[0]", "url") // You can use `ObjectEach` helper to iterate objects { "key1":object1, "key2":object2, .... "keyN":objectN } jsonparser.ObjectEach(data, func(key []byte, value []byte, dataType jsonparser.ValueType, offset int) error { fmt.Printf("Key: '%s'\n Value: '%s'\n Type: %s\n", string(key), string(value), dataType) return nil }, "person", "name") // The most efficient way to extract multiple keys is `EachKey` paths := [][]string{ []string{"person", "name", "fullName"}, []string{"person", "avatars", "[0]", "url"}, []string{"company", "url"}, } jsonparser.EachKey(data, func(idx int, value []byte, vt jsonparser.ValueType, err error){ switch idx { case 0: // []string{"person", "name", "fullName"} ... case 1: // []string{"person", "avatars", "[0]", "url"} ... case 2: // []string{"company", "url"}, ... } }, paths...)
若是只是单纯使用Get,返回值有四个,分别是:数组
value []byte, dataType ValueType, offset int, err error
能够发现,value是一个[]byte类型,实际取值须要手动将其转换为对应的类型;性能
第二个参数是自动推导的类型,支持的推导类型有:测试
const ( NotExist = ValueType(iota) String Number Object Array Boolean Null Unknown )
ret, err := jsonparser.GetInt(data, "person", "avatars", "[0]", "index")
err = jsonparser.ObjectEach(data, func(key []byte, value []byte, dataType jsonparser.ValueType, offset int) error { fmt.Printf("Key: '%s'\t Value: '%s'\t Type: %s\n", string(key), string(value), dataType) return nil }, "person", "name")
结果:jsonp
Key: 'first' Value: 'Leonid' Type: string Key: 'last' Value: 'Bugaev' Type: string Key: 'fullName' Value: 'Leonid Bugaev' Type: string
err = jsonparser.ObjectEach(data, func(key []byte, value []byte, dataType jsonparser.ValueType, offset int) error { fmt.Printf("Key: '%s'\t Value: '%s'\t Type: %s\n", string(key), string(value), dataType) return nil }, "person")
结果:编码
Key: 'name' Value: '{ "first": "Leonid", "last": "Bugaev", "fullName": "Leonid Bugaev" }' Type: object Key: 'github' Value: '{ "handle": "buger", "followers": 109 }' Type: object Key: 'avatars' Value: '[ {"index":100}, { "url": "https://avatars1.githubusercontent.com/u/14009?v=3&s=460", "type": "thumbnail" }, { "url1": "https://avatars2.githubusercontent.com/u/14009?v=3&s=460", "type": "thumbnail" } ]' Type: array
_, err = jsonparser.ArrayEach(data, func(value []byte, dataType jsonparser.ValueType, offset int, e error) { fmt.Printf("each, Value: '%s'\t Type: %s\n", string(value), dataType) }, "person", "avatars")
结果url
each, Value: '{"index":100}' Type: object each, Value: '{ "url": "https://avatars1.githubusercontent.com/u/14009?v=3&s=460", "type": "thumbnail" }' Type: object each, Value: '{ "url1": "https://avatars2.githubusercontent.com/u/14009?v=3&s=460", "type": "thumbnail" }' Type: object