使用jq将未知JSON标准化为指定Schema的技术求助
解决JSON格式统一的问题
需求回顾
你有两类JSON文件,需要将它们转换为统一结构:提取title、所有id值组成的列表、所有name值组成的列表。
两类输入格式分别为:
格式1
{ "title": "Some data", "data": [ { "id": "123", ... }, { "id": "abc", ... } ] }
格式2
{ "title": "Some more data", "data": [ { "ids": [ { "id": "123", ... }, { "id": "abc", ... } ], "names": [ { "name": "A", ... }, { "name": "B", ... } ] } ] }
目标输出
{ "title": "Some more data", "ids": [ "123", "abc" ], "names": [ "A", "B" ] }
现有脚本问题
你当前的jq脚本会生成重复title的对象,原因是错误地遍历了所有嵌套对象,导致每个id/name都生成一个独立对象。
正确实现脚本
下面的脚本可以精准处理两类格式,输出统一结构:
for f in $(find . -type f -name "*.json" | sort); do jq 'map({ title: .title, ids: ( if .data[0] | has("id") then .data[].id elif .data[0] | has("ids") then .data[0].ids[].id else [] end ), names: ( if .data[0] | has("names") then .data[0].names[].name else [] end ) })' "$f" > "${f}.tmp" && mv "${f}.tmp" "$f" done
脚本说明
map(...):遍历输入的JSON数组,对每个顶层对象单独处理- title:直接提取原对象的
title字段 - ids列表:
- 先检查第一个
data元素是否包含id字段,若是则提取所有data对象的id - 若第一个
data元素包含ids数组,则遍历该数组提取每个子项的id - 无匹配时返回空数组
- 先检查第一个
- names列表:
- 检查第一个
data元素是否包含names数组,若是则提取所有子项的name - 无匹配时返回空数组
- 检查第一个
- 使用临时文件
${f}.tmp先保存结果,再替换原文件,避免直接写入导致的数据损坏
内容的提问来源于stack exchange,提问作者LuMa
相关产品推荐
相关产品推荐

