This is a creation in Article, where the information may have evolved or changed.
Brief introduction
What is Easyjson? According to the official website, Easyjson is an efficient, fast and easy-to-use structural Structs<-->json conversion package. Easyjson is not implemented using reflection, so the performance is 4-5 times more than the other JSON packages, 2-3 times faster than the JSON package that Golang comes with. The Easyjson goal is to keep the build code simple so that it can be easily optimized or fixed.
Installation
go get -u github.com/mailru/easyjson/go install github.com/mailru/easyjson/easyjsonorgo build -o easyjson github.com/mailru/easyjson/easyjson
Verify that the installation is successful.
$ easyjsonUsage of D:\Code\go\bin\easyjson.exe: -all generate marshaler/unmarshalers for all structs in a file -build_tags string build tags to add to generated file -leave_temps do not delete temporary files -lower_camel_case use lowerCamelCase names instead of CamelCase by default -no_std_marshalers don't generate MarshalJSON/UnmarshalJSON funcs -noformat do not run 'gofmt -w' on output file -omit_empty omit empty fields by default string specify the filename of the output -pkg process the whole package instead of just the given file -snake_case use snake_case names instead of CamelCase by default -stubs only generate stubs for marshaler/unmarshaler funcs
There are several options to be aware of:
-lower_camel_case:将结构体字段field首字母改为小写。如Name=>name。 -build_tags string:将指定的string生成到生成的go文件头部。 -no_std_marshalers:不为结构体生成MarshalJSON/UnmarshalJSON函数。 -omit_empty:没有赋值的field可以不生成到json,否则field为该字段类型的默认值。-output_filename:定义生成的文件名称。-pkg:对包内指定有`//easyjson:json`结构体生成对应的easyjson配置。-snke_case:可以下划线的field如`Name_Student`改为`name_student`。
Use
Remember to add to the structure you need to use easyjson
//easyjson:json
. As follows:
//easyjson:jsontype School struct {Name string`json:"name"`Addr string`json:"addr"`}//easyjson:jsontype Student struct {Id int `json:"id"`Name string `json:"s_name"`School School `json:"s_chool"`Birthday time.Time `json:"birthday"`}
Execute under the structure package
easyjson -all student.go
A new file appears in the directory at this time.
Code generated by Easyjson for marshaling/unmarshaling. Do not edit.package Easyjsonimport (json "Encoding/json" Easyjson "Github.com/mailru/easyjson" Jlexer "github.com/ Mailru/easyjson/jlexer "Jwriter" Github.com/mailru/easyjson/jwriter ")//Suppress Unused package warningvar (_ *json. Rawmessage_ *jlexer. Lexer_ *jwriter. Writer_ Easyjson. Marshaler) func Easyjsonb83d7b77decodestudygoeasyjson (in *jlexer. Lexer, out *student) {istoplevel: = in. Isstart () if in. IsNull () {if istoplevel {in. Consumed ()}in. Skip () return}in. Delim (' {') for!in. Isdelim ('} ') {key: = in. Unsafestring () in. Wantcolon () if in. IsNull () {in. Skip () in. Wantcomma () continue}switch key {case ' ID ': out. Id = Int (in. Int ()) Case ' s_name ': out. Name = string (in. String ()) Case ' S_chool ': Easyjsonb83d7b77decodestudygoeasyjson1 (in, &out. School) Case "Birthday": if data: = In. Raw (); In. Ok () {in. Adderror (out. Birthday). Unmarshaljson (data))}default:in. Skiprecursive ()}in. Wantcomma ()}in. Delim ('} ') if Istoplevel {in. Consumed ()}}func easyjsonb83d7b77encodEstudygoeasyjson (out *jwriter. Writer, in Student) {out. Rawbyte (' {') First: = True_ = Firstif!first {out. Rawbyte (', ')}first = Falseout. Rawstring ("\" id\ ":") out. int (int (in. ID)) if!first {out. Rawbyte (', ')}first = Falseout. Rawstring ("\" s_name\ ":") out. String (String (in. Name) if!first {out. Rawbyte (', ')}first = Falseout. Rawstring ("\" s_chool\ ":") Easyjsonb83d7b77encodestudygoeasyjson1 (out, in.) School) if!first {out. Rawbyte (', ')}first = Falseout. Rawstring ("\" birthday\ ":") out. Raw (in. Birthday). Marshaljson ()) out. Rawbyte ('} ')}//Marshaljson supports JSON. Marshaler Interfacefunc (v Student) Marshaljson ([]byte, error) {w: = Jwriter. Writer{}easyjsonb83d7b77encodestudygoeasyjson (&w, V) return w.buffer.buildbytes (), w.error}//MarshalEasyJSON Supports Easyjson. Marshaler Interfacefunc (v Student) Marshaleasyjson (w *jwriter. Writer) {Easyjsonb83d7b77encodestudygoeasyjson (W, v)}//Unmarshaljson supports JSON. Unmarshaler Interfacefunc (v *student) unmarshaljson (data []byte) error {r: = Jlexer. Lexer{data: Data}easyjsonb83d7b77decodestudygoeasyjson (&r, V) return R.error ()}//Unmarshaleasyjson supports Easyjson. Unmarshaler Interfacefunc (v *student) Unmarshaleasyjson (L *jlexer. Lexer) {Easyjsonb83d7b77decodestudygoeasyjson (L, v)}func Easyjsonb83d7b77decodestudygoeasyjson1 (in *jlexer). Lexer, out *school) {istoplevel: = in. Isstart () if in. IsNull () {if istoplevel {in. Consumed ()}in. Skip () return}in. Delim (' {') for!in. Isdelim ('} ') {key: = in. Unsafestring () in. Wantcolon () if in. IsNull () {in. Skip () in. Wantcomma () continue}switch key {case ' name ': Out. Name = string (in. String ()) Case ' addr ': out. ADDR = string (in. String ()) default:in. Skiprecursive ()}in. Wantcomma ()}in. Delim ('} ') if Istoplevel {in. Consumed ()}}func easyjsonb83d7b77encodestudygoeasyjson1 (out *jwriter. Writer, in School) {out. Rawbyte (' {') First: = True_ = Firstif!first {out. Rawbyte (', ')}first = Falseout. Rawstring ("\" name\ ":") out. String (String (in. Name) if!first {out. Rawbyte (', ')}first = Falseout. Rawstring ("\" addr\ ":") out. String (String (in. ADDR)) out. Rawbyte ('} ')}
Now you can write a test class.
package mainimport ( "studygo/easyjson" "time" "fmt")func main(){ s:=easyjson.Student{ Id: 11, Name:"qq", School:easyjson.School{ Name:"CUMT", Addr:"xz", }, Birthday:time.Now(), } bt,err:=s.MarshalJSON() fmt.Println(string(bt),err) json:=`{"id":11,"s_name":"qq","s_chool":{"name":"CUMT","addr":"xz"},"birthday":"2017-08-04T20:58:07.9894603+08:00"}` ss:=easyjson.Student{} ss.UnmarshalJSON([]byte(json)) fmt.Println(ss)}
Operation Result:
{"id":11,"s_name":"qq","s_chool":{"name":"CUMT","addr":"xz"},"birthday":"2017-08-04T20:58:07.9894603+08:00"} <nil>{121 {CwwwwwwwUMT xzwwwww} 2017-08-04 20:52:03.4066002 +0800 CST}
Performance Test Comparison
Benchmark Results
ffjson
Results is from February 4th, using the latest and ffjson
go1.6. Results is from go/codec
March 4th, using the LA Test and go/codec
go1.6.
Unmarshaling
| Lib | JSON size | MB/s | Allocs/op | b/op | |:---------|:----------|-----: |----------: |------: | | Standard | Regular | 22 | 218 | 10229 | | Standard | Small | 9.7 | 14 | 720 | | | | | | || Easyjson | Regular | 125 | 128 | 9794 | | Easyjson | Small | 67 | 3 | 128 | | | | | | || Ffjson | Regular | 66 | 141 | 9985 | | Ffjson | Small | 17.6 | 10 | 488 | | | | | | || Codec | Regular | 55 | 434 | 19299 | | Codec | Small | 29 | 7 | 336 | | | | | | || Ujson | Regular | 103 | N/A | N/A |
marshaling, one goroutine.
| lib | json size | MB/s | Allocs/op | b/op | |:----------|:----------|-----: |----------: |------: | | Standard | Regular | 75 | 9 | 23256 | | Standard | Small | 32 | 3 | 328 | | Standard | Large | 80 | 17 | 1.2M | | | | | | || Easyjson | Regular | 213 | 9 | 10260 | | easyjson* | Regular | 263 | 8 | 742 | | Easyjson | Small | 125 | 1 | 128 | | Easyjson | Large | 212 | 33 | 490k | | easyjson* | Large | 262 | 25 | 2879 | | | | | | || Ffjson | Regular | 122 | 153 | 21340 | | ffjson** | Regular | 146 | 152 | 4897 | | Ffjson | Small | 36 | 5 | 384 | | ffjson** | Small | 64 | 4 | 128 | | Ffjson | Large | 134 | 7317 | 818k | | ffjson** | Large | 125 | 7320 | 827k | | | | | | || Codec | Regular | 80 | 17 | 33601 | | codec*** | Regular | 108 | 9 | 1153 | | Codec | Small | 42 | 3 | 304 | | codec*** | Small | 56 | 1 | 48 | | Codec | Large | 73 | 483 | 2.5M | | codec*** | Large | 103 | 451 | 66007 | | | | | | || Ujson | Regular | 92 | N/A | N/A |
* Marshaling to a writer,** using ffjson.Pool()
, * * * reusing output slice instead of resetting it to nil
marshaling, concurrent.
| lib | json size | MB/s | Allocs/op | b/op | |:----------|:----------|-----: |----------: |------: | | Standard | Regular | 252 | 9 | 23257 | | Standard | Small | 124 | 3 | 328 | | Standard | Large | 289 | 17 | 1.2M | | | | | | || Easyjson | Regular | 792 | 9 | 10597 | | easyjson* | Regular | 1748 | 8 | 779 | | Easyjson | Small | 333 | 1 | 128 | | Easyjson | Large | 718 | 36 | 548k | | easyjson* | Large | 2134 | 25 | 4957 | | | | | | || Ffjson | Regular | 301 | 153 | 21629 | | ffjson** | Regular | 707 | 152 | 5148 | | Ffjson | Small | 62 | 5 | 384 | | ffjson** | Small | 282 | 4 | 128 | | Ffjson | Large | 438 | 7330 | 1.0M | | ffjson** | Large | 131 | 7319 | 820k | | | | | | || Codec | Regular | 183 | 17 | 33603 | | codec*** | Regular | 671 | 9 | 1157 | | Codec | Small | 147 | 3 | 304 | | codec*** | Small | 299 | 1 | 48 | | Codec | Large | 190 | 483 | 2.5M | | codec*** | Large | 752 | 451 | 77574 |
* Marshaling to a writer,** using Ffjson. Pool ()
, * * * reusing output slice instead of resetting it to nil