如何用jq将带点分隔键的JSON转换为嵌套对象/数组?
用jq将带点分隔键的JSON转换为嵌套对象/数组格式
完全可以用jq实现这个需求,它的字符串处理和递归构造能力刚好适配这类键路径展开的场景。以下是具体实现方案:
输入输出示例
输入(带点分隔键的JSON片段)
{ "Employees": [ { "id": 1, "name": "Alice", "address.street": "123 Main St", "address.city": "New York", "contactDetails.0.phone": "555-1234", "contactDetails.0.email": "alice@example.com", "contactDetails.1.phone": "555-5678" } ] }
输出(嵌套对象/数组格式)
{ "Employees": [ { "id": 1, "name": "Alice", "address": { "street": "123 Main St", "city": "New York" }, "contactDetails": [ { "phone": "555-1234", "email": "alice@example.com" }, { "phone": "555-5678" } ] } ] }
核心实现脚本
创建一个convert.jq文件,内容如下:
# 递归设置路径值,自动区分对象和数组 def setpath_recursive(obj; path; value): reduce path as $p (obj; if ($p | type) == "number" then # 处理数组:若当前节点为null则初始化为数组,索引不足时补null (. // []) | if length <= $p then . + [null] * ($p - length + 1) else . end | setpath([$p]; setpath_recursive(.[$p]; path[1:]; value)) else # 处理对象:若当前节点为null则初始化为对象 (. // {}) | setpath([$p]; setpath_recursive(.[$p]; path[1:]; value)) end ); # 将单个扁平对象转换为嵌套结构 def flatten_to_nested: reduce to_entries[] as $entry (null; # 拆分键路径,数字片段转为数值类型(识别数组索引) setpath_recursive(.; ($entry.key | split(".") | map(tonumber? // .)); $entry.value) ); # 对Employees数组的每个元素应用转换 .Employees |= map(flatten_to_nested)
使用方法
假设你的输入文件是input.json,执行以下命令完成转换:
jq -f convert.jq input.json > output.json
关键逻辑说明
setpath_recursive函数:递归处理路径片段,遇到数字则构建/扩展数组,遇到字符串则构建对象,自动补全数组缺失的索引位置(用null占位)。flatten_to_nested函数:遍历扁平对象的所有键值对,将带点的键拆分为路径数组,把能转为数字的片段转为数值(区分数组索引和普通字符串键),再调用递归函数构建嵌套结构。- 最终处理:对JSON中的
Employees数组每个元素应用转换,输出嵌套后的结果。
注意事项
- 如果你的键名本身包含
.(而非路径分隔符),需要提前对这些键做转义处理,否则会被误拆分为路径。 - 数组索引不连续时,会自动用null填充中间位置,这符合JSON数组的有序特性。
内容的提问来源于stack exchange,提问作者beks6
相关产品推荐
相关产品推荐

