使用jq生成JSON元素路径时,数字格式键的语法问题
解决jq生成数字格式键的有效访问路径问题
我基于现有jq查询实现了生成JSON对象内所有元素访问路径的功能,但遇到数字格式键的问题:生成的.00这类路径会触发编译错误,正确格式应该是."00"。我尝试用正则表达式改进,但嵌套结构下会生成""00""02" = "a"这种无效路径,求正确解法。
原查询代码
# source: https://github.com/jqlang/jq/issues/243 def path2text($value): def tos: if type == "number" then . else (tojson) end; reduce .[] as $segment (""; . + ($segment | if type == "string" then "." + . else "[\(.)]" end)) + " = \($value | tos)"; paths(scalars) as $p | getpath($p) as $v | $p | path2text($v)
尝试改进的代码
def quote_string_numbers($data): if (test("\\.\\d+") or test("\\d+")) then "\"" + . + "\"" else . end; def path2text($value): def tos: if type == "number" then . else tojson end; reduce .[] as $segment (""; . + ($segment | if type == "string" then quote_string_numbers("." + .) else "[\(.)]" end)) + " = \($value | tos)"; paths(scalars) as $p | getpath($p) as $v | $p | path2text($v)
正确解决方案
核心问题是要单独处理字符串键的引号逻辑,不要将路径前缀.和键混在一起处理,避免嵌套时出现重复引号。
修正后的代码
def path2text($value): def tos: if type == "number" then . else tojson end; def format_key($key): # 匹配纯数字或带小数的数字格式键 if $key | test("^\\d+(\\.\\d+)?$") then "\"\($key)\"" else $key end; reduce .[] as $segment (""; . + ($segment | if type == "string" then ".\(format_key($segment))" else "[\(.)]" end)) + " = \($value | tos)"; paths(scalars) as $p | getpath($p) as $v | $p | path2text($v)
说明
- 新增
format_key函数专门处理字符串键:用正则^\\d+(\\.\\d+)?$精准匹配纯数字、带小数的数字格式键,这类键需要用双引号包裹 - 拼接路径时,先处理键再和
.组合,避免把.也包含进引号里,彻底解决嵌套结构下的无效路径问题 - 测试嵌套结构
{ "00" : {"02" : "a", "banana" : "foo" }},会生成正确的路径:."00"."02" = "a"."00".banana = "foo"
内容的提问来源于stack exchange,提问作者taco_parcel
相关产品推荐
相关产品推荐

