# json-iterator使用
特点
json-iterator
是一款快且灵活的JSON
解析器,同时提供Java
和Go
两个版本。json-iterator
是最快的JSON
解析器。它最多能比普通的解析器快10倍之多- 独特的
iterator api
能够直接遍历JSON
,极致性能、0内存分配 - 从dsljson和jsonparser借鉴了大量代码。
# 1 性能对比
# 1.1 Java端性能对比
主流的
JSON
解析器是非常慢的。Jsoniter Java
版本可以比常用的jackson/gson/fastjson
快3倍。 如果你需要处理大量的JSON
格式的日志,你应该考虑一下用dsl-json
或者Jsoniter
来节约可观的成本。 根据dsl-json
的性能评测,JSON
格式序列化和反序列化的速度其实一点都不慢,甚至比thrift/avro
还要快。
# 1.2 Golang端性能对比
Jsoniter
的Golang
版本可以比标准库(encoding/json)
快6倍之多。而且这个性能是在不使用代码生成的前提下获得的。
# 2 下载依赖
go get github.com/json-iterator/go
1
# 3 简单应用示例
# 3.1 序列化Marshal
jsoniter
常用序列化函数如下
// 直接把结构体转化成字符串
MarshalToString(v interface{}) (string, error)
//把结构体转化成json,兼容go标准库encoding/json的序列化方法,返回一个字节切片和错误
Marshal(v interface{}) ([]byte, error)
//转化成字节切片,第一个参数是结构体对象,第二个参数是前缀字符串必须为"",第三个参数为缩进表示,只能是空格
MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)
1
2
3
4
5
6
2
3
4
5
6
package main
import (
"fmt"
"github.com/json-iterator/go"
)
// Student 测试转换json的结构体
type Student struct {
Name string `json:"name"`
Age int `json:"age"`
Address string `json:"address"`
Hobby []string `json:"hobby"`
}
func main() {
stu := Student{
Name: "张三",
Age: 18,
Address: "chengdu",
Hobby: []string{"football", "swimming", "travel", "sing"},
}
// Marshal(v interface{}) ([]byte, error)
//把结构体转化成json,兼容go标准库encoding/json的序列化方法,返回一个字节切片和错误
b, err := jsoniter.Marshal(stu)
if err != nil {
fmt.Println("transformation error: ", err)
}
//输出转化后的字符串
//{"name":"张三","age":18,"address":"chengdu","hobby":["football","swimming","travel","sing"]}
fmt.Println(string(b))
//直接把结构体转化成字符串MarshalToString,这里错误判断省略
str, _ := jsoniter.MarshalToString(stu)
//{"name":"张三","age":18,"address":"chengdu","hobby":["football","swimming","travel","sing"]}
fmt.Println(str)
//转化成字节切片,第一个参数是结构体对象,第二个参数是前缀字符串必须为"",第三个参数为缩进表示,只能是空格
b, _ = jsoniter.MarshalIndent(stu, "", " ")
//输出带格式的字符串
fmt.Println(string(b))
}
---------------------输出结果--------------------------------
调用了Calc的初始化方法
{"name":"张三","age":18,"address":"chengdu","hobby":["football","swimming","travel","sing"]}
{"name":"张三","age":18,"address":"chengdu","hobby":["football","swimming","travel","sing"]}
{
"name": "张三",
"age": 18,
"address": "chengdu",
"hobby": [
"football",
"swimming",
"travel",
"sing"
]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# 3.2 反序列化Unmarshal
jsoniter
常用反序列化函数如下
//把字节切片的JSON格式转换成对应的结构体
Unmarshal(data []byte, v interface{}) error
//把字符串的JSON格式转换成对应的结构体
UnmarshalFromString(str string, v interface{}) error
1
2
3
4
2
3
4
package main
import (
"fmt"
"github.com/json-iterator/go"
)
// Student 测试转换json的结构体
type Student struct {
Name string `json:"name"`
Age int `json:"age"`
Address string `json:"address"`
Hobby []string `json:"hobby"`
}
func main() {
//反序列化给一个结构体
var stu Student
var jsonBlob = []byte(`
{"name": "张三", "Age": 12,"Address":"chengdu","Hobby":["football", "swimming", "travel", "sing"]}
`)
//根据字节切片转换成结构体。注意这里传入的是结构体地址
err := jsoniter.Unmarshal(jsonBlob, &stu)
if err != nil {
fmt.Println("unmarshal error: ", err)
}
fmt.Printf("根据字节切片转换的结构体数据:%+v\n", stu)
//根据字节切片转换成结构体
var students []Student
var jsonSlice = []byte(`[
{"name": "张三", "Age": 12,"Address":"chengdu","Hobby":["football", "swimming", "travel", "sing"]},
{"name": "李四", "Age": 28,"Address":"sichuan","Hobby":["dance", "music"]}
]`)
//根据字节切片转换成结构体。把多个结构体json数据反序列化给结构体切片
err = jsoniter.Unmarshal(jsonSlice, &students)
if err != nil {
fmt.Println("unmarshal error: ", err)
}
fmt.Printf("根据字节切片转换的结构体数据:%+v\n", students)
//根据
var stu1 Student
stuStr := `{"name": "张三", "Age": 12,"Address":"chengdu","Hobby":["football", "swimming", "travel", "sing"]`
//根据字符串转换成结构体。注意这里传入的是结构体地址
jsoniter.UnmarshalFromString(stuStr, &stu1)
fmt.Printf("根据字符串转换的结构体数据:%+v\n", stu1)
}
--------------------------------输出结果---------------------------------------
调用了Calc的初始化方法
根据字节切片转换的结构体数据:{Name:张三 Age:12 Address:chengdu Hobby:[football swimming travel sing]}
根据字节切片转换的结构体数据:[{Name:张三 Age:12 Address:chengdu Hobby:[football swimming travel sing]} {Name:李四 Age:28 Address:sichuan Hobby:[dance music]}]
根据字符串转换的结构体数据:{Name:张三 Age:12 Address:chengdu Hobby:[football swimming travel sing]}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# 4 jsoniter.Get
# 获取深层嵌套JSON结构的值的快速方法
//惰性json实现保持[]byte并延迟解析,把 json 解析为 Any 对象
Get(data []byte, path ...interface{}) Any
//Any通用对象表示
//最简单的json实现持有字节切片,并延迟解析
type Any interface {
LastError() error
ValueType() ValueType
MustBeValid() Any
ToBool() bool
ToInt() int
ToInt32() int32
ToInt64() int64
ToUint() uint
ToUint32() uint32
ToUint64() uint64
ToFloat32() float32
ToFloat64() float64
ToString() string
ToVal(val interface{})
Get(path ...interface{}) Any
Size() int
Keys() []string
GetInterface() interface{}
WriteTo(stream *Stream)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main
import (
"fmt"
jsoniter "github.com/json-iterator/go"
)
// Student 测试转换json的结构体
type Student struct {
Name string `json:"name"`
Age int `json:"age"`
Address string `json:"address"`
Hobby []string `json:"hobby"`
}
func main() {
var jsonBlob = []byte(`
{"name": "张三", "Age": 12,"Address":"chengdu","Hobby":["football", "swimming", "travel", "sing"]}
`)
//获取深层嵌套JSON结构的值的快速方法
//返回一个数组指针
hobby := jsoniter.Get(jsonBlob, "Hobby")
fmt.Printf("%T\n",hobby)//*jsoniter.arrayLazyAny
//获取这个结构体Hobby元素下面的第二个元素值
str := jsoniter.Get(jsonBlob, "Hobby", 1).ToString()
fmt.Println(str) //swimming
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 5 NewDecoder
通过流的方式操作
json
,适用于大文件json
//NewDecoder适用于json/stream NewDecoder API。
//new decoder返回从r读取的新解码器。
//不是json/编码解码器,而是返回一个解码器
//更多信息请参考https://godoc.org/encoding/json#NewDecoder
NewDecoder(reader io.Reader) *Decoder
1
2
3
4
5
2
3
4
5
package main
import (
"fmt"
"strings"
"github.com/json-iterator/go"
)
func main() {
json := jsoniter.ConfigCompatibleWithStandardLibrary
reader := strings.NewReader(`{"branch":"beta","change_log":"add the rows{10}","channel":"fros","create_time":"2017-06-13 16:39:08","firmware_list":"","md5":"80dee2bf7305bcf179582088e29fd7b9","note":{"CoreServices":{"md5":"d26975c0a8c7369f70ed699f2855cc2e","package_name":"CoreServices","version_code":"76","version_name":"1.0.76"},"FrDaemon":{"md5":"6b1f0626673200bc2157422cd2103f5d","package_name":"FrDaemon","version_code":"390","version_name":"1.0.390"},"FrGallery":{"md5":"90d767f0f31bcd3c1d27281ec979ba65","package_name":"FrGallery","version_code":"349","version_name":"1.0.349"},"FrLocal":{"md5":"f15a215b2c070a80a01f07bde4f219eb","package_name":"FrLocal","version_code":"791","version_name":"1.0.791"}},"pack_region_urls":{"CN":"https://s3.cn-north-1.amazonaws.com.cn/xxx-os/ttt_xxx_android_1.5.3.344.393.zip","default":"http://192.168.8.78/ttt_xxx_android_1.5.3.344.393.zip","local":"http://192.168.8.78/ttt_xxx_android_1.5.3.344.393.zip"},"pack_version":"1.5.3.344.393","pack_version_code":393,"region":"all","release_flag":0,"revision":62,"size":38966875,"status":3}`)
decoder := json.NewDecoder(reader)
params := make(map[string]interface{})
err := decoder.Decode(¶ms)
if err != nil {
fmt.Println(err)
} else {
//map[firmware_list: note:map[CoreServices:map[package_name:CoreServices version_code:76 version_name:1.0.76 md5:d26975c0a8c7369f70ed699f2855cc2e] FrDaemon:map[md5:6b1f0626673200bc2157422cd2103f5d package_name:FrDaemon version_code:390 version_name:1.0.390] FrGallery:map[version_code:349 version_name:1.0.349 md5:90d767f0f31bcd3c1d27281ec979ba65 package_name:FrGallery] FrLocal:map[version_name:1.0.791 md5:f15a215b2c070a80a01f07bde4f219eb package_name:FrLocal version_code:791]] pack_version:1.5.3.344.393 pack_version_code:393 status:3 channel:fros pack_region_urls:map[CN:https://s3.cn-north-1.amazonaws.com.cn/xxx-os/ttt_xxx_android_1.5.3.344.393.zip default:http://192.168.8.78/ttt_xxx_android_1.5.3.344.393.zip local:http://192.168.8.78/ttt_xxx_android_1.5.3.344.393.zip] release_flag:0 size:3.8966875e+07 md5:80dee2bf7305bcf179582088e29fd7b9 region:all revision:62 change_log:add the rows{10} create_time:2017-06-13 16:39:08 branch:beta]
fmt.Printf("%+v\n", params)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 6 标准库兼容配置
ConfigCompatibleWithStandardLibrary
尝试与标准库行为100%兼容配置
package main
import (
"fmt"
"github.com/json-iterator/go"
)
// Student 测试转换json的结构体
type Student struct {
Name string `json:"name"`
Age int `json:"age"`
Address string `json:"address"`
Hobby []string `json:"hobby"`
}
func main() {
stu := Student{
Name: "张三",
Age: 18,
Address: "chengdu",
Hobby: []string{"football", "swimming", "travel", "sing"},
}
//返回与标准库行为100%兼容的配置对象,返回encoding/json的操作对象
var json = jsoniter.ConfigCompatibleWithStandardLibrary
b, err := json.Marshal(stu)
if err != nil {
fmt.Println("transformation error: ", err)
}
fmt.Println(string(b))
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30