Golang High Performance JSON package: Easyjson

Source: Internet
Author: User
Tags lexer
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

ffjsonResults 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

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.