

Go 语言操作 JSON 的几种方法
source link: https://www.tuicool.com/articles/IJjEJnz
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

标准库的 json 模块
Go 语言标准库 encoding/json
提供了操作 JSON 的方法,一般可以使用 json.Marshal
和 json.Unmarshal
来序列化和解析 JSON 字符串:
// 定义结构体 type User struct { Email string `json:"email"` Password string `json:"password"` } // 序列化 buf, err := json.Marshal(User{ Email: "[email protected]", Password: "123456", }) // 解析 user := User {} err := json.Unmarshal([]byte(`{ "email": "[email protected]", "password": "123456" }`), &user)
更加灵活和更好性能的 jsoniter 模块
标准库 encoding/json
在使用时需要预先定义结构体,使用时显得不够灵活。这时候可以尝试使用 github.com/json-iterator/go
模块,其除了 提供与标准库一样的接口之外,还提供了一系列更加灵活的操作方法
。
val := []byte(`{"ID":1,"Name":"Reds","Colors":["Crimson","Red","Ruby","Maroon"]}`) // 仅解析 Colors 字段,并直接得到 string 类型 str := jsoniter.Get(val, "Colors", 0).ToString()
另辟蹊径提高性能的 easyjson 模块
标准库 encoding/json
需要依赖反射来实现,因此性能上会比较差。 github.com/mailru/easyjson
则是利用 go generate
机制自动为结构体生成实现了 MarshalJSON
和 UnmarshalJSON
方法的代码,在序列化和解析时可以直接生成对应字段的 JSON 数据,而不需要运行时反射。据官方的介绍,其性能是标准库的 4~5 倍,是其他 json 模块的 2~3 倍。
要使用 easyjson
模块,首先执行以下命令安装 easyjson
命令:
go get -u github.com/mailru/easyjson/...
然后新建文件 school.go
,并定义结构体 School
:
//easyjson:json type School struct { Name string `json:"name"` Addr string `json:"addr"` }
接着执行 easyjson -all school.go
,此时目录下会生成一个新的文件 school_easyjson.go
,为 School
结构体实现了 MarshalJSON
和 UnmarshalerJSON
方法,接着使用 easyjson 对应的方法去对这个结构体进行解析即可。
简单性能测试结果
对于以上介绍的三个模块,我测试了对于以下 JSON 字符串其序列化和解析性能的测试结果。
测试程序:
package awesomeProject import ( "encoding/json" "testing" jsoniter "github.com/json-iterator/go" "github.com/mailru/easyjson" ) type T1 struct { Name string `json:"name"` Age int `json:"age"` Intro string `json:"intro"` Valid bool `json:"valid"` } // easyjson:json type T2 struct { Name string `json:"name"` Age int `json:"age"` Intro string `json:"intro"` Valid bool `json:"valid"` } var d1 = T1{Name: "如何快速提升", Age: 12320, Intro: "如何快速提升 Go 程序性能?如何快速提升 Go 程序性能?如何快速提升 Go 程序性能?Well, easyJson is 4 times faster than normal json(as per its documets) ,in our organization we have used it extensively and yes its faster. Here is a small example to get started. my current directory name is easyJson", Valid: true} var d2 = T2{Name: "如何快速提升", Age: 12320, Intro: "如何快速提升 Go 程序性能?如何快速提升 Go 程序性能?如何快速提升 Go 程序性能?Well, easyJson is 4 times faster than normal json(as per its documets) ,in our organization we have used it extensively and yes its faster. Here is a small example to get started. my current directory name is easyJson", Valid: true} var s1 []byte func init() { buf, err := json.Marshal(&d1) if err != nil { panic(err) } s1 = buf println(string(s1)) } func BenchmarkStdJsonMarshal(b *testing.B) { i := 0 for i < b.N { i++ _, err := json.Marshal(&d1) if err != nil { panic(err) } } } func BenchmarkStdJsonUnmarshal(b *testing.B) { i := 0 var d T1 for i < b.N { i++ err := json.Unmarshal(s1, &d) if err != nil { panic(err) } } } func BenchmarkJsoniterMarshal(b *testing.B) { i := 0 for i < b.N { i++ _, err := jsoniter.Marshal(&d1) if err != nil { panic(err) } } } func BenchmarkJsoniterUnmarshal(b *testing.B) { i := 0 var d T1 for i < b.N { i++ err := jsoniter.Unmarshal(s1, &d) if err != nil { panic(err) } } } func BenchmarkJsoniterAny(b *testing.B) { i := 0 var d T1 for i < b.N { i++ a := jsoniter.Get(s1) d.Name = a.Get("name").ToString() d.Age = a.Get("age").ToInt() d.Intro = a.Get("intro").ToString() d.Valid = a.Get("valid").ToBool() } } func BenchmarkJsoniterAnyLight(b *testing.B) { i := 0 var d T1 for i < b.N { i++ a := jsoniter.Get(s1) d.Name = a.Get("name").ToString() } } func BenchmarkEasyJsonMarshal(b *testing.B) { i := 0 for i < b.N { i++ _, err := easyjson.Marshal(d2) if err != nil { panic(err) } } } func BenchmarkEasyJsonUnmarshal(b *testing.B) { i := 0 var d T2 for i < b.N { i++ err := easyjson.Unmarshal(s1, &d) if err != nil { panic(err) } } }
JSON 字符串:
{ "name":"如何快速提升", "age":12320, "intro":"如何快速提升 Go 程序性能?如何快速提升 Go 程序性能?如何快速提升 Go 程序性能?Well, easyJson is 4 times faster than normal json(as per its documets) ,in our organization we have used it extensively and yes its faster. Here is a small example to get started. my current directory name is easyJson", "valid":true }
测试结果:
- BenchmarkStdJsonMarshal-4, 使用标准库序列化,1098 ns/op
- BenchmarkStdJsonUnmarshal-4, 使用标准库解析,5006 ns/op
- BenchmarkJsoniterMarshal-4, 使用 jsoniter 序列化,1106 ns/op
- BenchmarkJsoniterUnmarshal-4, 使用 jsoniter 解析,816 ns/op
- BenchmarkJsoniterAny-4,使用 jsoniter 的 Any 解析,4092 ns/op
- BenchmarkJsoniterAnyLight-4,使用 jsoniter 的 Any 解析一个字段,1263 ns/op
- BenchmarkEasyJsonMarshal-4, 使用 easyjson 序列化,1658 ns/op
- BenchmarkEasyJsonUnmarshal-4, 使用 easyjson 解析,952 ns/op
从以上结果可以看到, jsoniter
在序列化和解析时均有比较好的性能, easyjson
次之,标准库 json
则在解析时性能比较差。当然,这并不是一个比较严格的性能测试,比如没有考虑内存分配问题以及多种不同的 JSON 结构和数据长度的测试。但是,
如果综合考虑性能和灵活性, jsoniter
可能是一个不错的选择。
参考资料
Recommend
-
46
标准库的 json 模块 Go 语言标准库 encoding/json 提供了操作 JSON 的方法,一般可以使用 json.Marshal 和 json.Unmarshal 来序列化和解析 JSON 字符串: // 定义结构体 type...
-
12
在C语言程序开发中,涉及到内存分配时,无论程序员使用的是静态内存,还是基于堆栈的动态分配,都必须谨慎的进行。嵌入式C语言程序员永远不能忽视内存安全问题。每一个C语言程序都会用到 RAM,但是使用的具体分配方式差异很大,本专栏接下来将讨论C语言...
-
6
为了了解 PHP、JSP、ASP 出现之前人们写网站的方法,洒家研究了一波 CGI,使用 C、Python、batch、shell script 语言写了几个简单的网页。 CGI 即通用网关接口,指 Web 服务器调用编程语言编写的程序的一个接口。洒家用的是 Apache 的 CGI,QUERY_...
-
4
在之前介绍了很多破解相关的文章,在这个过程中我们难免会遇到一些反调试策略,当时只是简单的介绍了如何去解决反调试,其实在去年我已经介绍了一篇关于Android中的安全逆向防护之战的文章:
-
5
Golang处理json动态key的几种情况 2018-05-03 12:45:14 code 约 920 字 预计阅读 2 分钟...
-
4
自然语言处理中CNN模型几种常见的Max Pooling操作 创建时间:2019-05-13 15:09 字数:1,052 阅读:81...
-
6
Java 截取字符串的几种操作-51CTO.COM Java 截取字符串的几种操作 作者:指北君 2022-07-18 08:18:11 在这篇文章中,我们学习了在Java中把一个 String 截断为特定数量的字符的各种方...
-
4
.NET MVC3 几种返回 JSON 对象的方式和注意事项 精选 原创 .NET MVC3 几种返回 JSON 对象的方式和注意事项引言 在用 .N...
-
7
Spring Boot中操作数据库的几种并发事务方式 当有多个并发事务时,会发生丢失更新异常。...
-
19
使用Handler和RunnableHandler类可以发送和处理与线程相关的消息和Runnable对象。通过postDelayed方法可以将一个Runnable对象延迟一段时间后再执行。Handler handler = new Handler(); Runnable runnable = new Runnabl...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK