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 Gin实现文件上传下载的示例代码
Apr 02 Golang
基于go interface{}==nil 的几种坑及原理分析
Apr 24 Golang
golang 接口嵌套实现复用的操作
Apr 29 Golang
golang协程池模拟实现群发邮件功能
May 02 Golang
go语言中GOPATH GOROOT的作用和设置方式
May 05 Golang
解决goland 导入项目后import里的包报红问题
May 06 Golang
使用golang编写一个并发工作队列
May 08 Golang
Golang表示枚举类型的详细讲解
Sep 04 Golang
golang为什么要统一错误处理
Apr 03 Golang
Golang map映射的用法
Apr 22 Golang
Golang 实现 WebSockets 之创建 WebSockets
Apr 24 Golang
Golang解析JSON对象
Apr 30 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
PHP5.0对象模型探索之抽象方法和抽象类
2006/09/05 PHP
php函数array_merge用法一例(合并同类数组)
2013/02/03 PHP
基于PHP导出Excel的小经验 完美解决乱码问题
2013/06/10 PHP
php版微信公众平台开发之验证步骤实例详解
2016/09/23 PHP
PHP实现对文件锁进行加锁、解锁操作的方法
2017/07/04 PHP
Js 随机数产生6位数字
2010/05/13 Javascript
DOM 高级编程
2015/05/06 Javascript
Javascript实现图片轮播效果(二)图片序列节点的控制实现
2016/02/17 Javascript
JavaScript操作HTML DOM节点的基础教程
2016/03/11 Javascript
使用JavaScript判断用户输入的是否为正整数(两种方法)
2017/02/05 Javascript
JavaScript实现替换字符串中最后一个字符的方法
2017/03/07 Javascript
JavaScript+HTML5实现的日期比较功能示例
2017/07/12 Javascript
详解用node搭建简单的静态资源管理器
2017/08/09 Javascript
bootstrap table实现双击可编辑、添加、删除行功能
2017/09/27 Javascript
Vue利用路由钩子token过期后跳转到登录页的实例
2017/10/26 Javascript
浅谈vuex 闲置状态重置方案
2018/01/04 Javascript
vue插件mescroll.js实现移动端上拉加载和下拉刷新
2019/03/07 Javascript
VUE脚手架的下载和配置步骤详解
2019/04/01 Javascript
vue循环数组改变点击文字的颜色
2019/10/14 Javascript
js里面的变量范围分享
2020/07/18 Javascript
VUE异步更新DOM - 用$nextTick解决DOM视图的问题
2020/11/06 Javascript
Python的__builtin__模块中的一些要点知识
2015/05/02 Python
Python爬取国外天气预报网站的方法
2015/07/10 Python
Python之多线程爬虫抓取网页图片的示例代码
2018/01/10 Python
浅谈在django中使用redirect重定向数据传输的问题
2020/03/13 Python
python中openpyxl和xlsxwriter对Excel的操作方法
2021/03/01 Python
使用CSS变量实现炫酷惊人的悬浮效果
2019/04/26 HTML / CSS
Smilodox官方运动服装店:从运动服到健身配件
2020/08/27 全球购物
车间主管岗位职责
2013/11/14 职场文书
大三学生做职业规划:给未来找个方向
2014/02/24 职场文书
三关爱志愿服务活动方案
2014/08/17 职场文书
毕业实习自我鉴定范文2014
2014/09/26 职场文书
学校总务处领导班子民主生活会对照检查材料思想汇报
2014/09/27 职场文书
给老婆的检讨书1000字
2015/01/01 职场文书
大学学生会主席竞选稿
2015/11/19 职场文书
励志语录:只有自己足够强大,才能不被别人践踏
2020/01/09 职场文书