gjson

gjson

高性能Go语言JSON解析工具

GJSON是一款高性能的Go语言JSON解析工具。它采用简洁的API设计,支持点表示法路径、数据迭代和JSON Lines处理等特性。GJSON在保持高速解析的同时,还具备出色的内存效率,适合处理大规模JSON数据。该库能够轻松完成从基础值提取到复杂查询等多种JSON操作任务,为Go开发者提供了强大而灵活的JSON处理方案。

GJSONJSON解析Go语言性能优化路径语法Github开源项目
<p align="center"> <picture> <source media="(prefers-color-scheme: dark)" srcset="/.github/images/logo-dark.png"> <source media="(prefers-color-scheme: light)" srcset="/.github/images/logo-light.png"> <img src="https://yellow-cdn.veclightyear.com/835a84d5/47774047-e108-4830-9533-8692cabf6783.png" width="240" alt="GJSON" > </picture> <br> <a href="https://godoc.org/github.com/tidwall/gjson"><img src="https://yellow-cdn.veclightyear.com/835a84d5/bf32198d-517d-4d30-ad0e-226471027d1c.svg?style=flat-square" alt="GoDoc"></a> <a href="https://tidwall.com/gjson-play"><img src="https://yellow-cdn.veclightyear.com/835a84d5/25e44863-e8ed-4b94-b3af-6bdef56b9b0f.svg?style=flat-square" alt="GJSON Playground"></a> <a href="SYNTAX.md"><img src="https://yellow-cdn.veclightyear.com/835a84d5/aae7435e-30c1-4b02-87fa-faba4710b722.svg?style=flat-square" alt="GJSON Syntax"></a> </p> <p align="center">快速获取JSON值</a></p>

GJSON是一个Go语言包,提供了一种快速简单的方法来获取JSON文档中的值。它具有诸如一行检索、点号路径语法、迭代和解析JSON行等特性。

另外还可以查看用于修改JSON的SJSON,以及命令行工具JJ

本README是GJSON使用的快速概述,更多信息请查看GJSON语法

GJSON也可用于PythonRust

入门

安装

要开始使用GJSON,请安装Go并运行go get

$ go get -u github.com/tidwall/gjson

这将检索该库。

获取值

Get函数在JSON中搜索指定路径。路径使用点号语法,例如"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用于处理JSON字节切片。

路径语法

以下是路径语法的快速概述,更完整的信息请查看GJSON语法

路径是由点分隔的一系列键。 键可以包含特殊通配符字符'*'和'?'。 要访问数组值,请使用索引作为键。 要获取数组中的元素数量或访问子路径,请使用'#'字符。 点和通配符字符可以用''转义。

{ "name": {"first": "Tom", "last": "Anderson"}, "age":37, "children": ["Sara","Alex","Jack"], "fav.movie": "Deer Hunter", "friends": [ {"first": "Dale", "last": "Murphy", "age": 44, "nets": ["ig", "fb", "tw"]}, {"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]}, {"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]} ] }
"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"
friends.#(first!%"D*").last        >> "Craig"
friends.#(nets.#(=="fb"))#.first   >> ["Dale","Roger"]

请注意,在v1.3.0之前,查询使用#[...]括号。这在v1.3.0中被更改,以避免与新的多路径语法混淆。为了向后兼容,#[...]将继续工作,直到下一个主要版本。

结果类型

GJSON支持JSON类型stringnumberboolnull。 数组和对象以原始JSON类型返回。

Result类型包含以下之一:

bool,用于JSON布尔值
float64,用于JSON数字
string,用于JSON字符串字面量
nil,用于JSON null

要直接访问值:

result.Type // 可以是String、Number、True、False、Null或JSON result.Str // 存储字符串 result.Num // 存储float64数字 result.Raw // 存储原始json result.Index // 原始值在原始json中的索引,零表示索引未知 result.Indexes // 匹配包含'#'查询字符的路径上所有元素的索引

有多种适用于结果的便捷函数:

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类型之一:

boolean >> bool number >> float64 string >> string null >> nil array >> []interface{} object >> map[string]interface{}

result.Array() 函数返回一个值数组。如果结果表示不存在的值,则返回空数组。如果结果不是JSON数组,返回值将是包含一个结果的数组。

64位整数

result.Int()result.Uint() 调用能够读取全部64位,允许处理大型JSON整数。

result.Int() int64 // -9223372036854775808 到 9223372036854775807 result.Uint() uint64 // 0 到 18446744073709551615

修饰符和路径链接

1.2版本新增了对修饰符函数和路径链接的支持。

修饰符是对json执行自定义处理的路径组件。

多个路径可以使用管道字符"链接"在一起。这对于从修改后的查询中获取结果很有用。

例如,在上述json文档上使用内置的 @reverse 修饰符,我们将获取 children 数组并反转顺序:

"children|@reverse"           >> ["Jack","Alex","Sara"]
"children|@reverse|0"         >> "Jack"

目前有以下内置修饰符:

  • @reverse: 反转数组或对象的成员。
  • @ugly: 从json文档中删除所有空白。
  • @pretty: 使json文档更易读。
  • @this: 返回当前元素。可用于检索根元素。
  • @valid: 确保json文档有效。
  • @flatten: 扁平化数组。
  • @join: 将多个对象合并为单个对象。
  • @keys: 返回对象的键数组。
  • @values: 返回对象的值数组。
  • @tostr: 将json转换为字符串。包装json字符串。
  • @fromstr: 将字符串从json转换。解包json字符串。
  • @group: 对对象数组进行分组。参见 e4fc67c
  • @dig: 无需提供完整路径即可搜索值。参见 e8e87f2

修饰符参数

修饰符可以接受可选参数。参数可以是有效的JSON文档或仅字符。

例如,@pretty 修饰符将json对象作为其参数。

@pretty:{"sortKeys":true} 

这会使json更美观并对其所有键进行排序。

{ "age":37, "children": ["Sara","Alex","Jack"], "fav.movie": "Deer Hunter", "friends": [ {"age": 44, "first": "Dale", "last": "Murphy"}, {"age": 68, "first": "Roger", "last": "Craig"}, {"age": 47, "first": "Jane", "last": "Murphy"} ], "name": {"first": "Tom", "last": "Anderson"} }

@pretty 的完整选项列表包括 sortKeysindentprefixwidth。 更多信息请参见 Pretty Options

自定义修饰符

您也可以添加自定义修饰符。

例如,这里我们创建一个修饰符,将整个json文档转换为大写或小写。

gjson.AddModifier("case", func(json, arg string) string { if arg == "upper" { return strings.ToUpper(json) } if arg == "lower" { return strings.ToLower(json) } return json })
"children|@case:upper"           >> ["SARA","ALEX","JACK"]
"children|@case:lower|@reverse"  >> ["jack","alex","sara"]

JSON Lines

使用 .. 前缀支持 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 })

获取嵌套数组值

假设你想从以下json中获取所有的姓氏:

{ "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()) // 打印 "Elliotte"

遍历对象或数组

ForEach 函数允许快速遍历对象或数组。 对于对象,键和值会被传递给迭代器函数。 对于数组,只传递值。 从迭代器返回 false 将停止迭代。

result := gjson.Get(json, "programmers") result.ForEach(func(key, value gjson.Result) bool { println(value.String()) return true // 继续迭代 })

简单解析和获取

有一个 Parse(json) 函数可以进行简单解析,以及 result.Get(path) 可以搜索结果。

例如,以下所有操作都会返回相同的结果:

gjson.Parse(json).Get("name").Get("last") gjson.Get(json, "name").Get("last") gjson.Get(json, "name.last")

检查值是否存在

有时你只想知道某个值是否存在。

value := gjson.Get(json, "name.last") if !value.Exists() { println("没有姓氏") } else { println(value.String()) } // 或者一步完成 if gjson.Get(json, "name.last").Exists() { println("有姓氏") }

验证 JSON

Get*Parse* 函数假定 json 格式良好。格式错误的 json 不会引发 panic,但可能返回意外结果。

如果你正在处理来自不可预测来源的 JSON,那么你可能想在使用 GJSON 之前进行验证。

if !gjson.Valid(json) { return errors.New("无效的 json") } value := gjson.Get(json, "name.last")

解析到 map

要解析到 map[string]interface{}:

m, ok := gjson.Parse(json).Value().(map[string]interface{}) if !ok { // 不是 map }

处理字节

如果你的 JSON 包含在 []byte 切片中,可以使用 GetBytes 函数。这比 Get(string(data), path) 更可取。

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) }

这是一种尽最大努力不分配原始 json 子切片的方法。这种方法利用了 result.Index 字段,它是原始 json 中原始数据的位置。result.Index 的值可能等于零,在这种情况下,result.Raw 会被转换为 []byte

性能

GJSON 与 encoding/jsonffjsonEasyJSONjsonparserjson-iterator 的基准测试对比

BenchmarkGJSONGet-16                11644512       311 ns/op       0 B/op	       0 allocs/op
BenchmarkGJSONUnmarshalMap-16        1122678      3094 ns/op    1920 B/op	      26 allocs/op
BenchmarkJSONUnmarshalMap-16          516681      6810 ns/op    2944 B/op	      69 allocs/op
BenchmarkJSONUnmarshalStruct-16       697053      5400 ns/op     928 B/op	      13 allocs/op
BenchmarkJSONDecoder-16               330450     10217 ns/op    3845 B/op	     160 allocs/op
BenchmarkFFJSONLexer-16              1424979      2585 ns/op     880 B/op	       8 allocs/op
BenchmarkEasyJSONLexer-16            3000000       729 ns/op     501 B/op	       5 allocs/op
BenchmarkJSONParserGet-16            3000000       366 ns/op      21 B/op	       0 allocs/op
BenchmarkJSONIterator-16             3000000       869 ns/op     693 B/op	      14 allocs/op

使用的 JSON 文档:

{ "widget": { "debug": "on", "window": { "title": "Sample Konfabulator Widget", "name": "main_window", "width": 500, "height": 500 }, "image": { "src": "Images/Sun.png", "hOffset": 250, "vOffset": 250, "alignment": "center" }, "text": { "data": "Click Here", "size": 36, "style": "bold", "vOffset": 100, "alignment": "center", "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;" } } }

每个操作都轮流使用以下搜索路径之一:

widget.window.name
widget.image.hOffset
widget.text.onMouseUp

这些基准测试是在 MacBook Pro 16" 2.4 GHz Intel Core i9 上使用 Go 1.17 运行的,可以在这里找到。

编辑推荐精选

Keevx

Keevx

AI数字人视频创作平台

Keevx 一款开箱即用的AI数字人视频创作平台,广泛适用于电商广告、企业培训与社媒宣传,让全球企业与个人创作者无需拍摄剪辑,就能快速生成多语言、高质量的专业视频。

即梦AI

即梦AI

一站式AI创作平台

提供 AI 驱动的图片、视频生成及数字人等功能,助力创意创作

扣子-AI办公

扣子-AI办公

AI办公助手,复杂任务高效处理

AI办公助手,复杂任务高效处理。办公效率低?扣子空间AI助手支持播客生成、PPT制作、网页开发及报告写作,覆盖科研、商业、舆情等领域的专家Agent 7x24小时响应,生活工作无缝切换,提升50%效率!

TRAE编程

TRAE编程

AI辅助编程,代码自动修复

Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。

AI工具TraeAI IDE协作生产力转型热门
蛙蛙写作

蛙蛙写作

AI小说写作助手,一站式润色、改写、扩写

蛙蛙写作—国内先进的AI写作平台,涵盖小说、学术、社交媒体等多场景。提供续写、改写、润色等功能,助力创作者高效优化写作流程。界面简洁,功能全面,适合各类写作者提升内容品质和工作效率。

AI辅助写作AI工具蛙蛙写作AI写作工具学术助手办公助手营销助手AI助手
问小白

问小白

全能AI智能助手,随时解答生活与工作的多样问题

问小白,由元石科技研发的AI智能助手,快速准确地解答各种生活和工作问题,包括但不限于搜索、规划和社交互动,帮助用户在日常生活中提高效率,轻松管理个人事务。

热门AI助手AI对话AI工具聊天机器人
Transly

Transly

实时语音翻译/同声传译工具

Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。

讯飞智文

讯飞智文

一键生成PPT和Word,让学习生活更轻松

讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。

AI办公办公工具AI工具讯飞智文AI在线生成PPTAI撰写助手多语种文档生成AI自动配图热门
讯飞星火

讯飞星火

深度推理能力全新升级,全面对标OpenAI o1

科大讯飞的星火大模型,支持语言理解、知识问答和文本创作等多功能,适用于多种文件和业务场景,提升办公和日常生活的效率。讯飞星火是一个提供丰富智能服务的平台,涵盖科技资讯、图像创作、写作辅助、编程解答、科研文献解读等功能,能为不同需求的用户提供便捷高效的帮助,助力用户轻松获取信息、解决问题,满足多样化使用场景。

热门AI开发模型训练AI工具讯飞星火大模型智能问答内容创作多语种支持智慧生活
Spark-TTS

Spark-TTS

一种基于大语言模型的高效单流解耦语音令牌文本到语音合成模型

Spark-TTS 是一个基于 PyTorch 的开源文本到语音合成项目,由多个知名机构联合参与。该项目提供了高效的 LLM(大语言模型)驱动的语音合成方案,支持语音克隆和语音创建功能,可通过命令行界面(CLI)和 Web UI 两种方式使用。用户可以根据需求调整语音的性别、音高、速度等参数,生成高质量的语音。该项目适用于多种场景,如有声读物制作、智能语音助手开发等。

下拉加载更多