要使用 jq
扁平化 JSON 数据,可以根据具体的需求采用不同的方法。以下是几种常见的场景及其对应的解决方案:
假设有以下嵌套的 JSON 数据:
json{
"user": {
"name": "张三",
"address": {
"city": "北京",
"zip": "100000"
},
"emails": ["zhangsan@example.com", "zs@example.cn"]
},
"active": true
}
希望将其扁平化为:
json{
"user.name": "张三",
"user.address.city": "北京",
"user.address.zip": "100000",
"user.emails": ["zhangsan@example.com", "zs@example.cn"],
"active": true
}
可以使用 jq
的递归函数来实现:
bashjq -r 'paths(scalars) as $path | { ($path | map(tostring) | join(".")): getpath($path) }' input.json
解释:
paths(scalars)
:获取所有叶子节点的路径。map(tostring) | join(".")
:将路径数组转换为点分隔的字符串。getpath($path)
:根据路径获取对应的值。注意: 这种方法适用于简单的扁平化需求,但对于复杂的嵌套结构可能需要更复杂的处理。
假设有以下包含嵌套数组的 JSON 数据:
json{
"users": [
{
"name": "张三",
"emails": ["zhangsan@example.com", "zs@example.cn"]
},
{
"name": "李四",
"emails": ["lisi@example.com"]
}
]
}
希望将其扁平化为:
json[
{ "user.name": "张三", "user.emails[0]": "zhangsan@example.com", "user.emails[1]": "zs@example.cn" },
{ "user.name": "李四", "user.emails[0]": "lisi@example.com" }
]
可以使用 jq
的递归展开功能:
bashjq '.users[] | with_entries(.key |= "user." + .) | flatten' input.json
不过,更通用的方法是使用递归函数来处理任意深度的嵌套:
bashjq '
def flatten:
reduce paths(scalars) as $path ({}; . + { ($path | map(tostring) | join(".")): getpath($path) });
.users[] | flatten
' input.json
但为了更好地处理数组索引,可以使用如下方法:
bashjq '
def flatten:
if type == "object" then
map_values(flatten) | with_entries(.key |= "user." + .)
elif type == "array" then
map(flatten) | .[]
else
.
end;
.users[] | flatten
' input.json
更简洁的方法:
如果只是想将数组元素展开为单独的对象,可以使用 jq
的 map
和 to_entries
:
bashjq '.users[] | {user: {name: .name, emails: .emails}}' input.json
但对于更复杂的扁平化需求,建议使用递归函数。
以下是一个通用的递归扁平化函数,适用于各种嵌套结构:
bashjq '
def flatten:
if type == "object" then
reduce keys[] as $k ({}; . + { ($k): (getpath([$k]) | flatten) })
elif type == "array" then
map(flatten) | flatten
else
.
end;
flatten
' input.json
使用示例:
假设有以下 JSON 数据:
json{
"a": 1,
"b": {
"c": 2,
"d": [3, 4, {"e": 5}]
},
"f": [6, {"g": 7}]
}
应用上述 flatten
函数后,输出将为:
json{
"a": 1,
"b.c": 2,
"b.d[0]": 3,
"b.d[1]": 4,
"b.d[2].e": 5,
"f[0]": 6,
"f[1].g": 7
}
假设有以下 JSON 数据 input.json
:
json{
"id": 1,
"details": {
"name": "张三",
"contact": {
"phone": "1234567890",
"email": "zhangsan@example.com"
}
},
"roles": ["admin", "user"]
}
要将其扁平化为:
json{
"id": 1,
"details.name": "张三",
"details.contact.phone": "1234567890",
"details.contact.email": "zhangsan@example.com",
"roles[0]": "admin",
"roles[1]": "user"
}
可以使用以下 jq
命令:
bashjq '
def flatten:
if type == "object" then
reduce keys[] as $k ({}; . + { ($k): (getpath([$k]) | flatten) })
elif type == "array" then
map(flatten) | flatten
else
.
end;
flatten
' input.json
输出结果:
json{
"id": 1,
"details.name": "张三",
"details.contact.phone": "1234567890",
"details.contact.email": "zhangsan@example.com",
"roles[0]": "admin",
"roles[1]": "user"
}
领取专属 10元无门槛券
手把手带您无忧上云