Go中使用gjson来操作JSON数据的实现


Posted in Golang onAugust 14, 2022

项目地址: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数据的实现的文章就介绍到这了,更多相关Go gjson操作JSON内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Golang 相关文章推荐
go语言-在mac下brew升级golang
Apr 25 Golang
goland 恢复已更改文件的操作
Apr 28 Golang
golang 实现菜单树的生成方式
Apr 28 Golang
golang 定时任务方面time.Sleep和time.Tick的优劣对比分析
May 05 Golang
Go 自定义package包设置与导入操作
May 06 Golang
go语言中http超时引发的事故解决
Jun 02 Golang
K8s部署发布Golang应用程序的实现方法
Jul 16 Golang
使用GO语言实现Mysql数据库CURD的简单示例
Aug 07 Golang
Golang MatrixOne使用介绍和汇编语法
Apr 19 Golang
Golang解析JSON对象
Apr 30 Golang
Go调用Rust方法及外部函数接口前置
Jun 14 Golang
go goth封装第三方认证库示例详解
Aug 14 Golang
Go gorilla/sessions库安装使用
Aug 14 #Golang
Go gorilla securecookie库的安装使用详解
Aug 14 #Golang
go goth封装第三方认证库示例详解
Aug 14 #Golang
基于Python实现西西成语接龙小助手
Aug 05 #Golang
Python测试框架pytest核心库pluggy详解
Aug 05 #Golang
Go结合Gin导出Mysql数据到Excel表格
Aug 05 #Golang
GO中sync包自由控制并发示例详解
Aug 05 #Golang
You might like
php中对2个数组相加的函数
2011/06/24 PHP
PHP代码网站如何防范SQL注入漏洞攻击建议分享
2012/03/01 PHP
php实现字符串翻转的方法
2015/03/27 PHP
Windows下php+mysql5.7配置教程
2017/05/16 PHP
javascript document.images实例
2008/05/27 Javascript
通过Mootools 1.2来操纵HTML DOM元素
2009/09/15 Javascript
输入自动提示搜索提示功能的使用说明:sugggestion.txt
2013/09/02 Javascript
javascript读取Xml文件做一个二级联动菜单示例
2014/03/17 Javascript
jquery实现标签上移、下移、置顶
2015/04/26 Javascript
详细解读AngularJS中的表单验证编程
2015/06/19 Javascript
一起学写js Calender日历控件
2016/04/14 Javascript
easyui datagrid 大数据加载效率慢,优化解决方法(推荐)
2016/11/09 Javascript
小程序开发实战:实现九宫格界面的导航的代码实现
2017/01/19 Javascript
Bootstrap路径导航与分页学习使用
2017/02/08 Javascript
初学者AngularJS的环境搭建过程
2017/10/27 Javascript
微信小程序如何获取用户信息
2018/01/26 Javascript
Vue 中对图片地址进行拼接的方法
2018/09/03 Javascript
JavaScript类型相关的常用操作总结
2019/02/14 Javascript
微信小程序利用for循环解决内容变更问题
2020/03/05 Javascript
[02:28]DOTA2 2015国际邀请赛中国区预选赛首日现场百态
2015/05/26 DOTA
Python教程之全局变量用法
2016/06/27 Python
python自动发送测试报告邮件功能的实现
2019/01/22 Python
Python代码实现http/https代理服务器的脚本
2019/08/12 Python
Django 拆分model和view的实现方法
2019/08/16 Python
Python通过VGG16模型实现图像风格转换操作详解
2020/01/16 Python
python 实现性别识别
2020/11/21 Python
Bibloo荷兰:女士、男士和儿童的服装、鞋子和配饰
2019/02/25 全球购物
银行办理业务介绍信
2014/01/18 职场文书
工程开工庆典邀请函
2014/02/01 职场文书
法律进企业活动方案
2014/03/04 职场文书
文化建设工作方案
2014/05/12 职场文书
学生抄作业检讨书(2篇)
2014/10/17 职场文书
初中家长评语大全
2014/12/26 职场文书
2016年端午节寄语
2015/12/04 职场文书
CSS3实现的水平标题菜单
2021/04/14 HTML / CSS
HTML中link标签属性的具体用法
2023/05/07 HTML / CSS