scan4all 依赖组件解析:GJSON 路径语法(Path Syntax)完全指南

scan4all 依赖组件解析:GJSON 路径语法(Path Syntax)完全指南 scan4all 依赖组件解析GJSON 路径语法Path Syntax完全指南【免费下载链接】scan4allOfficial repository vuls Scan: 15000PoCs; 23 kinds of application password crack; 7000Web fingerprints; 146 protocols and 90000 rules Port scanning; Fuzz, HW, awesome BugBounty( ͡° ͜ʖ ͡°)...项目地址: https://gitcode.com/GitHub_Trending/sca/scan4all导读GJSON 是一个用于快速、无结构地从 JSON 载荷中按路径表达式检索数值的 Go 库而 GJSON Path 则是一种用文本字符串描述搜索模式的语言。本指南以 scan4all 仓库中 vendor 目录下的 GJSON 源码及其官方语法文档 SYNTAX.md 为主体系统讲解路径结构、通配符、数组查询、修饰符Modifiers、多路径Multipaths与字面量Literals的完整用法。读完本文你将能够熟练编写从简单取值到嵌套过滤、数组拼接、结果重塑的全部 GJSON 路径表达式并理解其背后的源码实现。说明GJSON 在本仓库中以间接依赖形式存在见 go.mod版本为github.com/tidwall/gjson v1.16.0其完整实现位于 vendor/github.com/tidwall/gjson/gjson.go。因此本文讨论的语法能力与版本行为均以仓库内这份 v1.16.0 源码为准。路径结构Path StructureGJSON Path 的定位是快速从 JSON 载荷中检索数值的搜索模式。它被设计为一系列以.字符分隔的组件components。除了.之外还有几个字符具有特殊含义分别是字符含义.标准路径分隔符\|管道分隔符在数组#之后使用时与.行为不同#深入 JSON 数组、查询数组、获取数组长度修饰符前缀如reverse、pretty\转义字符*通配符匹配任意 0 个及以上字符!通配符之外的声明字符也是 JSON 字面量的起始声明符?通配符匹配任意 1 个字符示例数据与基础取值Basic文档给出的示例 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]} ] }多数情况下你只需按对象名或数组下标取值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开始friends.1.first这类路径表示先取第 1 个元素再取其中的first字段。在源码实现层面入口函数为 gjson.go 中的 Get接受字符串以及 GetBytes接受[]byte避免字符串与字节切片间不必要的拷贝。通配符Wildcards键名中可以包含特殊通配符*和?*匹配任意0 个及以上字符?匹配任意1 个字符。child*.2 Jack c?ildren.0 Sarachild*.2中child*匹配了children这一键名再取下标2得到Jackc?ildren.0中?占位一个字符同样命中children。转义字符Escape Character.、*、?等特殊字符可以通过\转义为普通字面量。示例 JSON 中的fav.movie键名本身含有.直接写fav.movie会被拆成两级路径因此必须转义fav\.movie Deer Hunter需要注意在源代码中硬编码路径字符串时\本身也要按宿主语言的转义规则处理。文档分别给出了 Go 与 Rust 两种写法// Go val : gjson.Get(json, fav\\.movie) // must escape the slash val : gjson.Get(json, fav\.movie) // no need to escape the slash// Rust let val gjson::get(json, fav\\.movie) // must escape the slash let val gjson::get(json, r#fav\.movie#) // no need to escape the slash即用双引号字符串时需写成fav\\.movie用 Go 反引号原始字符串或 Rust 的r#...#原始字符串时直接写fav\.movie即可。数组Arrays与#符号#字符用于深入 JSON 数组获取数组长度单独使用#。批量取值#后跟字段名会对数组的每个元素提取该字段并组装成新数组。friends.# 3 friends.#.age [44,68,47]friends.#返回friends数组的长度3friends.#.age则提取每个好友的age字段得到[44,68,47]。查询Queries基本查询#(...)与#(...)#可以对数组进行查询#(...)返回第一个匹配项#(...)#返回所有匹配项。查询支持以下比较操作符数值/字符串比较、!、、、、简单模式匹配%like匹配与!%not like不匹配friends.#(lastMurphy).first Dale friends.#(lastMurphy)#.first [Dale,Jane] friends.#(age45)#.last [Craig,Murphy] friends.#(first%D*).last Murphy friends.#(first!%D*).last Craig逐条解读friends.#(lastMurphy).first在friends中找第一个last Murphy的元素取它的first得到Dale。friends.#(lastMurphy)#.first找所有last Murphy的元素并取first得到[Dale,Jane]Dale 与 Jane 同姓 Murphy。friends.#(age45)#.last找所有年龄大于 45 的好友的last得到[Craig,Murphy]。friends.#(first%D*).last%为 like 匹配第一个first以D开头Dale的元素的last得到Murphy。friends.#(first!%D*).last!%为 not like第一个first不以D开头Roger的元素的last得到Craig。查询非对象值如果数组中存放的是非对象值如字符串可以省略操作符右侧的字符串children.#(!%*a*) Alex children.#(%*a*)# [Sara,Jack]children.#(%*a*)#取所有包含字母a的元素Sara、Jackchildren.#(!%*a*)取第一个不含a的元素Alex。嵌套查询查询是允许嵌套的。下面的路径先找出所有nets中包含fb的好友再取这些好友的firstfriends.#(nets.#(fb))#.first [Dale,Roger]兼容性说明文档特别注明在 v1.3.0 之前查询使用的是#[...]方括号语法例如friends#[lastMurphy].first。v1.3.0 为了与新增的多路径Multipaths语法避免混淆改为#(...)。出于向后兼容#[...]在下一个大版本之前仍可继续工作。~波浪号操作符布尔转换与存在性判断~操作符会在比较前把值转换为布尔。支持的四种类型为~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即~true把真值true-ish视为true~false把假值false-ish以及不存在的值视为true~null把null与不存在的值视为true~*把任何存在的值视为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命中了b为布尔true、字符串1、数字1、字符串true的 4 个元素a 为 2、6、7、8~false命中了布尔false、字符串0、数字0以及完全不存在的字段a11 的元素没有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]b~nullb为nulla10或不存在a11。b~*b存在a1 到 10。b!~*b不存在仅 a11。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)#单独使用返回两个 Murphy 好友的完整对象数组。后缀.first在返回结果之前对每个数组元素处理first路径于是整体结果是[Dale,Jane]。后缀|first在得到上一步结果之后再处理first路径。由于上一步结果是一个数组不是对象first不存在因此得到non-existent。后缀|0因为0是上一步结果的第一个下标因此返回{first: Dale, last: Murphy, age: 44}。后缀.0对数组每个元素取下标0而每个元素是对象没有下标 0返回[]。后缀. #同理返回[]而|#是对结果数组求长度得到2。一句话总结在#之后.X是元素级投影|X是结果级操作。这是编写复杂 GJSON 查询时最容易踩坑、也最值得理解的区别。修饰符Modifiers修饰符是一种对 JSON 执行自定义处理的路径组件写法为名称。文档以内置reverse为例反转children数组children.reverse [Jack,Alex,Sara] children.reverse.0 Jack当前内置的修饰符完整清单如下以仓库内 v1.16.0 为准源码见 gjson.goreverse反转数组或反转对象的成员顺序。ugly移除 JSON 中所有空白字符输出最紧凑的 JSON。pretty将 JSON 输出为更易读的格式化文本。this返回当前元素可用于取回根元素例如路径this直接返回整个 JSON。valid校验 JSON 文档是否合法常用于多路径构造新文档后的正确性检查。flatten扁平化数组将嵌套数组摊平为一层。join将多个对象合并为单个对象。keys返回对象所有键组成的数组。values返回对象所有值组成的数组。tostr将 JSON 转换为字符串给 JSON 字符串加引号包装。fromstr从字符串解析为 JSON去掉引号解包。group对对象数组按某字段分组详见提交e4fc67c。dig无需给出完整路径即可搜索某个值详见提交e8e87f2。修饰符参数Modifier arguments修饰符可以接收可选参数参数既可以是合法的 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换行宽度。自定义修饰符Custom modifiers除了内置修饰符你还可以通过gjson.AddModifier注册自定义修饰符。在仓库源码中该函数定义于 gjson.go签名是func AddModifier(name string, fn func(json, arg string) string)回调函数接收两个字符串参数json为当前处理的 JSON 文本arg为冒号后传入的参数返回处理后的 JSON 文本。文档给出一个把 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]注意自定义修饰符与内置修饰符可以链式组合如children.case:lower.reverse先转小写再反转文档同时注明自定义修饰符目前在 Rust 版本中尚不可用仅 Go 版本支持。多路径Multipaths自 v1.3.0 起GJSON 支持将多条路径拼接成新文档用逗号分隔多条路径并包裹在[...]或{...}中分别生成新数组或新对象。例如{name.first,age,the_murphys:friends.#(lastMurphy)#.first}这里选取了name.first、age以及所有last Murphy好友的first。可以发现可以提供一个可选键名如the_murphys来强制为某个值指定键否则使用字段自身的名字此处为first如果无法确定名字则使用_作为占位键。结果为{first:Tom,age:37,the_murphys:[Dale,Jane]}多路径的典型用途是从一次 JSON 检索中聚合多个关注点输出结构化的新文档非常适合配合后续的valid做结果校验或配合pretty做输出美化。字面量Literals自 v1.12.0 起GJSON 支持JSON 字面量用于构造静态的 JSON 片段在配合多路径Multipaths构建新文档时尤其有用。JSON 字面量以!声明字符开头。例如{name.first,age,company:!Happysoft,employed:!true}这里选取了name.first和age然后新增两个字段company字符串字面量Happysoft与employed布尔字面量true{first:Tom,age:37,company:Happysoft,employed:true}借助字面量多路径可以构建出动态取值 静态字段混合的完整 JSON 文档无需在代码里手动拼接字符串。小结与实战提示GJSON 路径语法的设计哲学是一次字符串表达一次检索从最简单的name.last到复杂的friends.#(nets.#(fb))#.first与{name.first,age,the_murphys:friends.#(lastMurphy)#.first}都不需要编写遍历代码。综合全文给出几条实战要点先写简单路径再逐步叠加先用friends.#确认数组再依次加查询、投影与修饰符便于定位语义错误。分清.与|在#之后的差异需要结果级操作如对结果数组取下标、求长度时使用|需要元素级投影时使用.。善用~系列与%系列操作符~true/~false/~null/~*可以优雅处理布尔语义与字段不存在的情况%/!%解决模式匹配。用多路径 字面量构造输出文档{...}/[...]包裹多条路径配合!字面量字段可以把检索、过滤、重组一步完成。注意版本差异#(...)取代#[...]发生在 v1.3.0字面量自 v1.12.0 起可用本仓库 vendor 中的实现为 v1.16.0已全部支持上述语法。若需在代码中注册自定义修饰符可参考 gjson.go 中 AddModifier 的签名并在程序初始化阶段调用。如需在线验证语法行为可使用官方提供的 GJSON Playground 进行实验在 Go 工程中则直接调用 Get / GetBytes单路径或 GetMany / GetManyBytes多路径返回[]Result即可。【免费下载链接】scan4allOfficial repository vuls Scan: 15000PoCs; 23 kinds of application password crack; 7000Web fingerprints; 146 protocols and 90000 rules Port scanning; Fuzz, HW, awesome BugBounty( ͡° ͜ʖ ͡°)...项目地址: https://gitcode.com/GitHub_Trending/sca/scan4all创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考