前言,最近項目中須要動態解析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