尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Sliver 项目内置 GJSON 路径语法实战指南:快速检索 JSON 载荷的查询语言

发布时间:2026/9/25 6:06:05

资讯中心
01
ARTICLE

Sliver 项目内置 GJSON 路径语法实战指南:快速检索 JSON 载荷的查询语言

Sliver 项目内置 GJSON 路径语法实战指南:快速检索 JSON 载荷的查询语言
网络安全【免费下载链接】sliverAdversary Emulation Framework项目地址https://gitcode.com/gh_mirrors/sl/sliver点击查看免费下载导读GJSON Path 是一种用于从 JSON 载荷中快速检索值的文本字符串语法它允许你以简洁的表达式在一条路径内完成对象取值、数组遍历、条件过滤、结果重组与格式转换。本指南以 Sliver 项目 vendor 目录中内置的github.com/tidwall/gjson版本 v1.18.0见 go.mod的官方语法文档为核心结合其完整实现源码 vendor/github.com/tidwall/gjson/gjson.go 讲解每一种路径元素的写法、含义与执行时机。读完本文后你将能直接用gjson.Get(json, friends.#(age45)#.last)这类单行表达式替代多段解析代码并在自己的 Go 程序中通过自定义修饰器扩展查询能力。路径结构一条表达式描述一种搜索模式GJSON Path 的定位是用一条文本字符串描述在 JSON 载荷中的搜索模式它被设计为一系列由.分隔的组件name.last friends.1.first除了.之外还有几个具有特殊含义的字符|、#、、\、*、!、?。它们分别承担数组、查询、修饰器、转义、通配符、字面量等职责是掌握整套语法的基础。本文后续所有示例都基于下面这份示例 JSON{ 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]} ] }Basic按对象名与数组索引取值大多数场景下你只需要按对象字段名或数组下标取值路径与结果的对应关系如下name.last Anderson name.first Tom age 37 children [Sara,Alex,Jack] children.0 Sara children.1 Alex friends.1 {first: Roger, last: Craig, age: 68} friends.1.first Roger字段名逐级下钻数组直接用整数下标从 0 开始。这是 GJSON 使用频率最高的基础形态。Wildcards用*与?做键名模糊匹配一个键名中可以包含通配符*和?*匹配任意零个或更多字符?恰好匹配任意一个字符。child*.2 Jack c?ildren.0 Sarachild*.2借助*同时命中children再取下标 2 得到Jackc?ildren.0用?匹配children中的h字符c 任意 1 字符 ildren。通配符让路径对键名变化具有容错性适合批量、未知结构的数据探查。Escape character转义特殊字符当键名本身包含.、*、?等特殊字符时例如示例 JSON 中的fav.movie需要用反斜杠\转义fav\.movie Deer Hunter需要注意的是在 Go 源码中硬编码路径时普通字符串字面量里的\本身也要被转义因此存在两种写法// Go val : gjson.Get(json, fav\\.movie) // must escape the slash val : gjson.Get(json, fav\.movie) // no need to escape the slash第一种用双引号字符串需要写成\\才能让运行时真正拿到\.第二种用反引号原始字符串\原样保留更不易出错。Rust 版本gjson::get同理普通字符串需写成fav\\.movieraw stringr#fav\.movie#则无需转义。Arrays用#深入数组#字符专门用于挖掘 JSON 数组。单独使用#即可获得数组长度#放在字段名之后时则表示对数组中每个元素依次求值后续路径并把结果聚合成一个新数组friends.# 3 friends.#.age [44,68,47]friends.#返回元素个数 3friends.#.age则对三个朋友对象分别取age得到[44,68,47]。Queries用#(...)过滤数组元素基本比较与通配匹配可以对数组做条件查询#(...)返回第一个匹配元素#(...)#返回全部匹配元素。支持的比较运算符包括、!、、、、以及模式匹配运算符%like与!%not likefriends.#(lastMurphy).first Dale friends.#(lastMurphy)#.first [Dale,Jane] friends.#(age45)#.last [Craig,Murphy] friends.#(first%D*).last Murphy friends.#(first!%D*).last Craig要点#(...)只取首个匹配#(...)#收集所有匹配%后面的D*是通配模式D*匹配以D开头的名字!%则取反。对非对象元素的查询当数组元素本身不是对象而是字符串、数字等标量时可以省略运算符右侧的字符串直接对元素本身做比较或模式匹配children.#(!%*a*) Alex children.#(%*a*)# [Sara,Jack]children.#(!%*a*)返回第一个不含a的孩子名Alexchildren.#(%*a*)#返回所有含a的名字[Sara,Jack]。嵌套查询查询内部允许嵌套查询例如筛选社交网络列表中包含fb的朋友friends.#(nets.#(fb))#.first [Dale,Roger]nets.#(fb)是数组nets内部的元素查询左侧省略直接比较元素本身外层再对命中结果取.first。历史兼容性说明在 v1.3.0 之前查询使用的是#[...]方括号语法v1.3.0 为避免与后文 Multipaths 语法冲突而改为#(...)。出于向后兼容#[...]在下一个大版本发布之前仍会继续工作。Tilde 布尔转换~运算符~波浪号运算符会在比较前把值转换为布尔语义可用于表达真值/假值/是否存在等判定。支持的四种类型如下~true Converts true-ish values to true ~false Converts false-ish and non-existent values to true ~null Converts null and non-existent values to true ~* Converts any existing value to true对下面这份 JSON 做查询{ vals: [ { a: 1, b: data }, { a: 2, b: true }, { a: 3, b: false }, { a: 4, b: 0 }, { a: 5, b: 0 }, { a: 6, b: 1 }, { a: 7, b: 1 }, { a: 8, b: true }, { a: 9, b: false }, { a: 10, b: null }, { a: 11 } ] }查询所有真值true-ish或假值false-ish元素vals.#(b~true)#.a [2,6,7,8] vals.#(b~false)#.a [3,4,5,9,10,11]可以看到true、1、1、true均被当作真值false、0、0、null以及完全缺失的字段都被当作假值——{a:11}中不存在b字段也被~false捕获。查询 null 与显式存在性vals.#(b~null)#.a [10,11] vals.#(b~*)#.a [1,2,3,4,5,6,7,8,9,10] vals.#(b!~*)#.a [11]~null同时命中b: null与b缺失两种情形~*只要求字段存在值是什么不重要因此{a:11}被排除配合!反向后b!~*恰好选出字段缺失的元素。Dot vs Pipe.与|的执行时机差异.是标准分隔符但也可以用|代替。绝大多数情况下二者结果相同真正的差异出现在#数组/查询之后friends.0.first Dale friends|0.first Dale friends.0|first Dale friends|0|first Dale friends|# 3 friends.# 3 friends.#(lastMurphy)# [{first: Dale, last: Murphy, age: 44},{first: Jane, last: Murphy, age: 47}] friends.#(lastMurphy)#.first [Dale,Jane] friends.#(lastMurphy)#|first non-existent friends.#(lastMurphy)#.0 [] friends.#(lastMurphy)#|0 {first: Dale, last: Murphy, age: 44} friends.#(lastMurphy)#.# [] friends.#(lastMurphy)#|# 2逐条拆解差异的根源路径friends.#(lastMurphy)#本身的结果是数组[{first: Dale, last: Murphy, age: 44},{first: Jane, last: Murphy, age: 47}].first后缀会对前一步结果的每个数组元素先执行first再汇总得到[Dale,Jane]|first则是对上一步的整体结果一个数组而非对象执行first数组上没有first字段因此结果non-existent.0同理把0当作路径依次作用到每个元素上元素是对象而非数组取不到下标得到空数组[]而|0直接对数组结果取下标 0命中第一个元素对象.#对每个元素求长度失败得[]|#直接求数组长度得2。一句话总结.是映射语义对集合中每个元素求值|是管道语义对整体结果求值。理解这一点是避免写出意外空结果的关键。Modifiers内置修饰器与参数修饰器modifier是一种对 JSON 做自定义处理的路径组件写法为名称。例如内置的reverse可以反转数组children.reverse [Jack,Alex,Sara] children.reverse.0 Jack内置修饰器在 vendor/github.com/tidwall/gjson/gjson.go 中注册当前共有 13 个修饰器作用reverse反转数组或反转对象成员的顺序ugly移除 JSON 中所有空白字符pretty让 JSON 更易读美化输出this返回当前元素可用于取回根元素valid校验 JSON 文档是否合法flatten展平数组join将多个对象合并为单个对象keys返回对象的键名数组values返回对象的值数组tostr把 JSON 转换为字符串包一层 JSON 字符串fromstr从 JSON 字符串解包还原内层 JSONgroup对对象数组做分组dig无需给出完整路径即可搜索值修饰器参数修饰器可以接受一个可选参数参数可以是合法 JSON 载荷也可以是普通字符语法为name:参数。以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的完整选项为sortKeys、indent、prefix与width。从源码实现gjson.go可见pretty底层把参数解析为pretty.DefaultOptions通过sortKeys、indent等字段控制输出格式——这也解释了为何参数必须以 JSON 对象形式给出。自定义修饰器AddModifier你可以在 Go 中注册自己的修饰器。下面的例子创建了一个把整个 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]AddModifier的签名与注册表实现见 gjson.go第一个参数是修饰器名第二个参数是func(json, arg string) string回调接收被处理 JSON 与参数并返回新 JSON。需要留意的是该操作不是线程安全的应放在使用其他所有 gjson 函数之前执行源码注释明确说明这一点见 gjson.goModifierExists可用于检测某修饰器是否已注册。此外自定义修饰器目前仅在 Go 版本可用Rust 版本暂不支持。Multipaths把多条路径拼接成新文档自 v1.3.0 起GJSON 支持将多条路径拼接成新文档把逗号分隔的路径包在[...]中会生成新数组包在{...}中会生成新对象。例如{name.first,age,the_murphys:friends.#(lastMurphy)#.first}这里同时选取了名、年龄以及所有姓氏为 Murphy 的朋友的名。注意其中的可选键语法用the_murphys:前缀强制给某个值指定键名如果不指定键则使用实际字段名此处为first当无法确定字段名时使用_作为键名。最终结果为{first:Tom,age:37,the_murphys:[Dale,Jane]}Multipaths 是从一次解析中聚合出结构化结果的利器适合一条查询直接产出可用于日志、上报或二次处理的 JSON。Literals用!声明静态 JSON 字面量自 v1.12.0 起GJSON 支持 JSON 字面量用于在构造文档时加入静态 JSON 块在 Multipaths 场景下尤其有用。JSON 字面量以声明字符!开头。例如{name.first,age,company:!Happysoft,employed:!true}该表达式选取了名与年龄然后追加两个新字段company与employed结果为{first:Tom,age:37,company:Happysoft,employed:true}注意!之后直接跟 JSON 值字符串需加引号布尔、数字直接书写且字面量也可带自定义键名。在 Go 中使用路径语法核心 API 速览路径语法的实际执行入口都在 vendor/github.com/tidwall/gjson/gjson.go 中常用 API 包括函数说明gjson.Get(json, path)对字符串执行单条路径查询返回Result定义gjson.GetBytes(json []byte, path)对字节切片执行查询避免字符串拷贝定义gjson.GetMany(json, path...)一次解析同时执行多条路径定义gjson.Parse(json)/gjson.ParseBytes(json)预解析 JSON供后续多次查询复用定义gjson.AddModifier(name, fn)注册自定义修饰器定义查询返回的Result提供了丰富的取值方法String()、Bool()、Int()、Float()、Time()、Array()、Map()、ForEach()、Exists()见 gjson.go。其中Exists()的实现是t.Type ! Null || len(t.Raw) ! 0gjson.go这正是上文~*/~null等查询判断值是否存在的底层依据。Value()会把结果转成 Go 原生类型bool、float64、string、nil、map[string]interface{}、[]interface{}见 gjson.go。一个把上述内容串起来的 Go 示例import github.com/tidwall/gjson json : {name:{first:Tom},friends:[{first:Dale,last:Murphy},{first:Jane,last:Murphy}]} firstName : gjson.Get(json, name.first).String() // Tom murphys : gjson.GetMany(json, friends.#(last\Murphy\)#.first, friends.#.last) // 两个 Result if gjson.Get(json, friends.#(age45)).Exists() { // 存在年龄大于 45 的朋友 }实践建议与局限优先用GetBytes/Parse提升吞吐在需要反复查询同一载荷的循环中先Parse再取Result.Get比反复gjson.Get更高效处理[]byte时直接用GetBytes可避免不必要的字符串转换。区分.与|的语义对查询结果继续取字段用.映射到每个元素取整体结果的属性/下标用|这是最常见的结果为空排查点。自定义修饰器注意并发安全AddModifier需在程序早期、并发使用之前完成注册。版本差异查询语法#(...)、Multipaths 与 JSON 字面量分别自 v1.3.0、v1.3.0、v1.12.0 起可用旧式#[...]查询方括号写法仍兼容但即将在下一个大版本移除。当前仓库 vendor 中锁定的是 v1.18.0go.mod上述全部能力均可用。延伸阅读语法文档原始出处vendor/github.com/tidwall/gjson/SYNTAX.md完整实现源码vendor/github.com/tidwall/gjson/gjson.go内置修饰器注册表gjson.go#L2915-L2929依赖声明go.mod赞分享网络安全【免费下载链接】sliverAdversary Emulation Framework项目地址https://gitcode.com/gh_mirrors/sl/sliver点击查看免费下载相关推荐GJSON路径语法完全指南快速掌握JSON查询的终极技巧GJSON路径语法完全指南快速掌握JSON查询的终极技巧 GJSON是一款专为Go语言设计的高性能JSON解析工具它提供了简单直观的路径语法让开发者能够快序列化深入解析GJSON路径语法高效查询JSON数据的利器深入解析GJSON路径语法高效查询JSON数据的利器 GJSON是一个强大的Go语言JSON解析库其核心特性之一就是提供了一套简洁高效的路径查询语法。本文将序列化Karmada 项目中的 GJSON 实战指南Go 语言快速提取与解析 JSON 的路径语法、修饰器与零拷贝技巧Karmada 项目中的 GJSON 实战指南Go 语言快速提取与解析 JSON 的路径语法、修饰器与零拷贝技巧 导读 GJSON github.com/t云原生多集群集群管理微服务上一篇5大理由让你立即体验OpenFrontIO免费的在线实时战略游戏终极指南下一篇完整指南在Raspberry Pi上快速部署Windows ARM系统创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。