Go中使用gjson来操作JSON数据的实现
来源:脚本之家
时间:2023-01-07 12:08:18 141浏览 收藏
本篇文章主要是结合我之前面试的各种经历和实战开发中遇到的问题解决经验整理的,希望这篇《Go中使用gjson来操作JSON数据的实现》对你有很大帮助!欢迎收藏,分享给更多的需要的朋友学习~
项目地址:https://github.com/tidwall/gjson
下载:
$ go get -u github.com/tidwall/gjson
获取值
Get查询指定路径, 通过.
来区分. 比如"name.last"或者"age". 如果找到了匹配路径, 将返回结果.
package main import "github.com/tidwall/gjson" const json = `{"name":{"first":"Janet","last":"Prichard"},"age":47}` func main() { value := gjson.Get(json, "name.last") println(value.String()) }
输出结果:
Prichard
同时有 GetMany 方法批量获取值, 也有 GetBytes 方法获取字节切片.
路径解析
路径是一系列被.
分隔的key拼接而成. 路径可能包含通配符'*'和'?'. 通过下标访问数组值. 通过'#'来获取值在元素中的排位或访问子路径. .
和通配符可以通过''来转义.
{ "name": {"first": "Tom", "last": "Anderson"}, "age":37, "children": ["Sara","Alex","Jack"], "fav.movie": "Deer Hunter", "friends": [ {"first": "Dale", "last": "Murphy", "age": 44}, {"first": "Roger", "last": "Craig", "age": 68}, {"first": "Jane", "last": "Murphy", "age": 47} ] }
"name.last" >> "Anderson" "age" >> 37 "children" >> ["Sara","Alex","Jack"] "children.#" >> 3 "children.1" >> "Alex" "child*.2" >> "Jack" "c?ildren.0" >> "Sara" "fav\.movie" >> "Deer Hunter" "friends.#.first" >> ["Dale","Roger","Jane"] "friends.1.last" >> "Craig"
你同样能通过#[...]
来查询数组中的第一个匹配的项, 或通过'#[...]#'查询所有匹配的项. 查询支持==
, !=
, ,
,
>
, >=
比较运算符和'%'模糊匹配.
friends.#[last=="Murphy"].first >> "Dale" friends.#[last=="Murphy"]#.first >> ["Dale","Jane"] friends.#[age>45]#.last >> ["Craig","Murphy"] friends.#[first%"D*"].last >> "Murphy"
JSON 行
同样支持JSON Lines, 使用 ..
前缀, 把多行文档视作数组. 比如:
{"name": "Gilbert", "age": 61} {"name": "Alexa", "age": 34} {"name": "May", "age": 57} {"name": "Deloise", "age": 44}
..# >> 4 ..1 >> {"name": "Alexa", "age": 34} ..3 >> {"name": "Deloise", "age": 44} ..#.name >> ["Gilbert","Alexa","May","Deloise"] ..#[name="May"].age >> 57
ForEachLines
方法可以迭代json.
gjson.ForEachLine(json, func(line gjson.Result) bool{ println(line.String()) return true })
Result Type
GJSON支持json类型包括 string
, number
, bool
, and null
. 数组和对象被挡住基础类型返回. Result
持有如下其中一种类型:
bool, for JSON booleans float64, for JSON numbers string, for JSON string literals nil, for JSON null
直接访问value:
result.Type // can be String, Number, True, False, Null, or JSON result.Str // holds the string result.Num // holds the float64 number result.Raw // holds the raw json result.Index // index of raw value in original json, zero means index unknown
有各种各样的方便的函数可以获取结果:
result.Exists() bool result.Value() interface{} result.Int() int64 result.Uint() uint64 result.Float() float64 result.String() string result.Bool() bool result.Time() time.Time result.Array() []gjson.Result result.Map() map[string]gjson.Result result.Get(path string) Result result.ForEach(iterator func(key, value Result) bool) result.Less(token Result, caseSensitive bool) bool
result.Value()
方法返回 interface{}
Go基本类型之一. result.Array()
方法返回一组值. 如果结果是不存在的值, 将会返回空数组. 如果结果不是JSON数组, 将会返回只包含一个值的数组.
boolean >> bool number >> float64 string >> string null >> nil array >> []interface{} object >> map[string]interface{}
64-bit integers
result.Int()
和 result.Uint()
返回的是64位大数字.
result.Int() int64 // -9223372036854775808 to 9223372036854775807 result.Uint() int64 // 0 to 18446744073709551615
读取嵌套数组
假如你想从下列json获取所有的lastName:
{ "programmers": [ { "firstName": "Janet", "lastName": "McLaughlin", }, { "firstName": "Elliotte", "lastName": "Hunter", }, { "firstName": "Jason", "lastName": "Harold", } ] }
你可以使用如下路径programmers.#.lastName
:
result := gjson.Get(json, "programmers.#.lastName") for _, name := range result.Array() { println(name.String()) }
你同样能获取数组里的对象:
name := gjson.Get(json, `programmers.#[lastName="Hunter"].firstName`) println(name.String()) // prints "Elliotte"
对象或数组迭代
ForEach
方法允许你快速的迭代对象或数组. key和value被传递给对象的迭代器函数. 只有value被传递给数组. 迭代器返回false
将会终止迭代.
简易的Parse和Get
Parse(json)
方法可以简单的分析json, result.Get(path)
查询结果. 比如, 下面的几种情况都将返回相同的结果:
gjson.Parse(json).Get("name").Get("last") gjson.Get(json, "name").Get("last") gjson.Get(json, "name.last")
检查value是否存在
有时你想要知道值是否存在.
value := gjson.Get(json, "name.last") if !value.Exists() { println("no last name") } else { println(value.String()) } // Or as one step if gjson.Get(json, "name.last").Exists() { println("has a last name") }
验证JSON
Get*
和 Parse*
方法预期json格式是正常的, 如果不正常, 将会返回不可预料的结果. 如果你读取的json来源不可预料, 那么你可以通过GJSON这么事先验证.
if !gjson.Valid(json) { return errors.New("invalid json") } value := gjson.Get(json, "name.last")
反序列化到map
反序列化到map[string]interface{}
:
m, ok := gjson.Parse(json).Value().(map[string]interface{}) if !ok { // not a map } ## 处理Bytes 如果你的JSON包含字节数组切片, 与其调用`Get(string(data), path)`, 不如调用[GetBytes](https://godoc.org/github.com/tidwall/gjson#GetBytes)方法更优. ```go var json []byte = ... result := gjson.GetBytes(json, path)
如果你在使用gjson.GetBytes(json, path)
方法, 并且你想避免从result.Raw
转换到 []byte
, 你可以使用这种模式:
var json []byte = ... result := gjson.GetBytes(json, path) var raw []byte if result.Index > 0 { raw = json[result.Index:result.Index+len(result.Raw)] } else { raw = []byte(result.Raw) }
这是最好的模式, 不会为子切片重新分配内存. 这个模式使用了result.Index
字段, 它直接指向了raw data所处原来json中的位置. 如果result.Raw
是转换成[]byte
的, result.Index
将会为0.
一次获取多个值
GetMany
方法可以用于同时获取多个值.
results := gjson.GetMany(json, "name.first", "name.last", "age")
返回值是[]Result
类型, 总是返回正传入路径个数的数量.
好了,本文到此结束,带大家了解了《Go中使用gjson来操作JSON数据的实现》,希望本文对你有所帮助!关注golang学习网公众号,给大家分享更多Golang知识!
-
329 收藏
-
377 收藏
-
203 收藏
-
264 收藏
-
487 收藏
-
233 收藏
-
322 收藏
-
181 收藏
-
316 收藏
-
244 收藏
-
300 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 507次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习
-
- 寂寞的外套
- 这篇文章真是及时雨啊,好细啊,受益颇多,已收藏,关注up主了!希望up主能多写Golang相关的文章。
- 2023-03-09 13:34:41
-
- 笨笨的老师
- 这篇技术贴真及时,太详细了,很棒,mark,关注博主了!希望博主能多写Golang相关的文章。
- 2023-01-21 16:41:45
-
- 和谐的煎蛋
- 很详细,收藏了,感谢老哥的这篇文章,我会继续支持!
- 2023-01-18 17:54:11
-
- 典雅的大地
- 这篇文章真是及时雨啊,很详细,真优秀,码起来,关注博主了!希望博主能多写Golang相关的文章。
- 2023-01-18 17:37:41
-
- 优美的热狗
- 写的不错,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,帮助很大,总算是懂了,感谢师傅分享文章内容!
- 2023-01-16 18:34:31
-
- 健忘的微笑
- 写的不错,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,看完之后很有帮助,总算是懂了,感谢老哥分享技术贴!
- 2023-01-15 12:16:42
-
- 勤奋的哈密瓜
- 细节满满,码住,感谢楼主的这篇文章内容,我会继续支持!
- 2023-01-12 03:33:26
-
- 可爱的天空
- 太详细了,mark,感谢up主的这篇技术贴,我会继续支持!
- 2023-01-11 01:16:57
-
- 喜悦的鸡翅
- 很有用,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,看完之后很有帮助,总算是懂了,感谢作者大大分享技术贴!
- 2023-01-09 18:55:07
-
- 外向的面包
- 这篇技术文章真及时,楼主加油!
- 2023-01-09 02:51:16
-
- 善良的糖豆
- 这篇技术文章太及时了,太全面了,感谢大佬分享,码起来,关注楼主了!希望楼主能多写Golang相关的文章。
- 2023-01-08 05:28:51
-
- 开心的板栗
- 这篇文章真是及时雨啊,细节满满,很好,已加入收藏夹了,关注up主了!希望up主能多写Golang相关的文章。
- 2023-01-08 01:09:44