Golang高性能json包:easyjson
简介easyjson是什么呢? 根据官网介绍,easyjson是提供高效快速且易用的结构体structs<-->json转换包。easyjson并没有使用反射方式实现,所以性能比其他的json包该4-5倍,比golang 自带的json包快2-3倍。 easyjson目标是维持生成去代码简单,以致于它可以轻松地进行优化或固定。 安装go get -u github.com/mailru/easyjson/ go install github.com/mailru/easyjson/easyjson or go build -o easyjson github.com/mailru/easyjson/easyjson 验证是否安装成功。 $ easyjson Usage of D:Codegobineasyjson.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 其中有几个选项需要注意: -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`。 使用记得在需要使用 //easyjson:json type School struct { Name string `json:"name"` Addr string `json:"addr"` } //easyjson:json type Student struct { Id int `json:"id"` Name string `json:"s_name"` School School `json:"s_chool"` Birthday time.Time `json:"birthday"` } 在结构体包下执行 easyjson -all student.go 此时在该目录下出现一个新的文件。 // Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT. package easyjson import ( json "encoding/json" easyjson "github.com/mailru/easyjson" jlexer "github.com/mailru/easyjson/jlexer" jwriter "github.com/mailru/easyjson/jwriter" ) // suppress unused package warning var ( _ *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 _ = first if !first { out.RawByte(',') } first = false out.RawString(""id":") out.Int(int(in.Id)) if !first { out.RawByte(',') } first = false out.RawString(""s_name":") out.String(string(in.Name)) if !first { out.RawByte(',') } first = false out.RawString(""s_chool":") easyjsonB83d7b77EncodeStudygoEasyjson1(out,in.School) if !first { out.RawByte(',') } first = false out.RawString(""birthday":") out.Raw((in.Birthday).MarshalJSON()) out.RawByte('}') } // MarshalJSON supports json.Marshaler interface func (v Student) MarshalJSON() ([]byte,error) { w := jwriter.Writer{} easyjsonB83d7b77EncodeStudygoEasyjson(&w,v) return w.Buffer.BuildBytes(),w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface func (v Student) MarshalEasyJSON(w *jwriter.Writer) { easyjsonB83d7b77EncodeStudygoEasyjson(w,v) } // UnmarshalJSON supports json.Unmarshaler interface func (v *Student) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} easyjsonB83d7b77DecodeStudygoEasyjson(&r,v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (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 _ = first if !first { out.RawByte(',') } first = false out.RawString(""name":") out.String(string(in.Name)) if !first { out.RawByte(',') } first = false out.RawString(""addr":") out.String(string(in.Addr)) out.RawByte('}') } 现在可以写一个测试类啦。 package main import ( "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) } 运行结果: {"id":11,"birthday":"2017-08-04T20:58:07.9894603+08:00"} <nil> {121 {CwwwwwwwUMT xzwwwww} 2017-08-04 20:52:03.4066002 +0800 CST} 性能测试对比Benchmark Results
Unmarshaling
Marshaling,one goroutine.
* marshaling to a writer,** using Marshaling,concurrent.
* marshaling to a writer,*** reusing output slice instead of resetting it to nil (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |