github.com/fufuok/utils@v1.0.10/xjson/jsongen/README.md (about) 1 # 高效的 JSON 字符串生成器 2 3 ***forked from darjun/json-gen*** 4 5 使用原始数据项生成 JSON, 类似字符拼接, 支持常用类型. 6 7 性能比结构体序列化方式快挺多. 8 9 ## 改动 10 11 - 增加使用 `buffer_pool` 12 - 增加添加原始 JSON 数据方法: `RawString` `RawBytes` 13 - map: `m.PutRawString` `m.PutRawBytes` `m.PutRawStringArray` `m.PutRawBytesArray` 14 - array: `a.AppendRawString` `a.AppendRawBytes` `a.AppendRawStringArray` `a.AppendRawBytesArray` 15 - 减少一些不必要的转换 16 - 增加 `go mod` 17 18 ## 使用 19 20 简单使用请向下翻原文, 高性能场景建议配合 [bytespool](https://github.com/fufuok/bytespool) 使用: 21 22 ```go 23 package main 24 25 import ( 26 "fmt" 27 28 "github.com/fufuok/bytespool" 29 "github.com/fufuok/jsongen" 30 ) 31 32 func main() { 33 js := jsongen.NewMap() 34 js.PutString("s", `a"b"\c`) 35 js.PutFloat("f", 3.14) 36 js.PutBool("b", false) 37 jsArr := jsongen.NewArray() 38 jsArr.AppendInt(7) 39 jsArr.AppendStringArray([]string{"A", "B"}) 40 js.PutArray("sub", jsArr) 41 js.PutRawString("raw", `{"n":null,"m":[1,"ff"]}`) 42 43 size := js.Size() 44 bs := bytespool.Get(size) 45 defer bytespool.Put(bs) 46 data := js.Serialize(bs) 47 48 // 也可以直接使用 nil 49 // data := js.Serialize(nil) 50 51 fmt.Printf("%s\n", data) 52 53 // Output: 54 // {"s":"a\"b\"\\c","f":3.14,"b":false,"sub":[7,["A","B"]],"raw":{"n":null,"m":[1,"ff"]}} 55 } 56 ``` 57 58 59 60 # json-gen 61 62 [](https://travis-ci.org/darjun/json-gen) 63 64 ## 起源 65 66 游戏服务端的很多操作(包括玩家的和非玩家的)需要传给公司中台收集汇总,根据运营的需求分析数据。中台那边要求传过去的数据为 JSON 格式。开始使用 Golang 标准库中的`encoding/json`,发现性能不够理想(因为序列化使用了反射,涉及多次内存分配)。由于数据原始格式都是`map[string]interface{}`,且需要自己一个字段一个字段构造,于是我想可以在构造过程中就计算出最终 JSON 串的长度,那么就只需要一次内存分配了。 67 68 ## 使用 69 70 下载: 71 72 ``` 73 $ go get github.com/darjun/json-gen 74 ``` 75 76 引入: 77 78 ``` 79 import ( 80 jsongen "github.com/darjun/json-gen" 81 ) 82 ``` 83 84 构造数组或映射: 85 86 ``` 87 // 数组 88 a := jsongen.NewArray() 89 a.AppendUint(123) 90 a.AppendInt(-456) 91 data := a.Serialize(nil) 92 // string(data) == "[123,-456]" 93 94 // 映射 95 m := jsongen.NewMap() 96 m.PutUint("uintkey", 123) 97 m.PutInt("intkey", -456) 98 data := m.Serialize(nil) 99 // string(data) == `{"uintkey":123,"intkey":-456}` 100 ``` 101 102 当然类型可以无限嵌套: 103 104 ``` 105 subm := jsongen.NewMap() 106 subm.PutString("stringkey", "test string") 107 108 m := jsongen.NewMap() 109 m.PutUint("uintkey", 123) 110 m.PutUintArray("uintarray", []uint64{123,456,789}) 111 m.PutMap("subm", subm) 112 data := m.Serialize(nil) 113 // string(data) == `{"uintkey":123,"uintarray":[123,456,789],"subm":{"stringkey":"test string"}}` 114 ``` 115 116 ## Benchmark 117 118 | Library | Time/op(ns) | B/op | allocs/op | 119 |---------|---------|----------|-----------| 120 | encoding/json | 22209 | 6673 | 127 | 121 | darjun/json-gen | 3300 | 1152 | 1 | 122 123 通常情况下,`json-gen`生成 JSON 串的性能是标准 JSON 库的**10**。