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  [![Build Status](https://travis-ci.org/darjun/json-gen.svg?branch=master)](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**。