首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

使用jq扁平化JSON数据

要使用 jq 扁平化 JSON 数据,可以根据具体的需求采用不同的方法。以下是几种常见的场景及其对应的解决方案:

1. 将嵌套对象展开为扁平结构

假设有以下嵌套的 JSON 数据:

代码语言:javascript
复制
json{
  "user": {
    "name": "张三",
    "address": {
      "city": "北京",
      "zip": "100000"
    },
    "emails": ["zhangsan@example.com", "zs@example.cn"]
  },
  "active": true
}

希望将其扁平化为:

代码语言:javascript
复制
json{
  "user.name": "张三",
  "user.address.city": "北京",
  "user.address.zip": "100000",
  "user.emails": ["zhangsan@example.com", "zs@example.cn"],
  "active": true
}

可以使用 jq 的递归函数来实现:

代码语言:javascript
复制
bashjq -r 'paths(scalars) as $path | { ($path | map(tostring) | join(".")): getpath($path) }' input.json

解释:​

  • paths(scalars):获取所有叶子节点的路径。
  • map(tostring) | join("."):将路径数组转换为点分隔的字符串。
  • getpath($path):根据路径获取对应的值。
  • 最终生成一个扁平化的对象。

注意:​​ 这种方法适用于简单的扁平化需求,但对于复杂的嵌套结构可能需要更复杂的处理。

2. 将嵌套数组展开为扁平列表

假设有以下包含嵌套数组的 JSON 数据:

代码语言:javascript
复制
json{
  "users": [
    {
      "name": "张三",
      "emails": ["zhangsan@example.com", "zs@example.cn"]
    },
    {
      "name": "李四",
      "emails": ["lisi@example.com"]
    }
  ]
}

希望将其扁平化为:

代码语言:javascript
复制
json[
  { "user.name": "张三", "user.emails[0]": "zhangsan@example.com", "user.emails[1]": "zs@example.cn" },
  { "user.name": "李四", "user.emails[0]": "lisi@example.com" }
]

可以使用 jq 的递归展开功能:

代码语言:javascript
复制
bashjq '.users[] | with_entries(.key |= "user." + .) | flatten' input.json

不过,更通用的方法是使用递归函数来处理任意深度的嵌套:

代码语言:javascript
复制
bashjq '
  def flatten:
    reduce paths(scalars) as $path ({}; . + { ($path | map(tostring) | join(".")): getpath($path) });

  .users[] | flatten
' input.json

但为了更好地处理数组索引,可以使用如下方法:

代码语言:javascript
复制
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

更简洁的方法:​

如果只是想将数组元素展开为单独的对象,可以使用 jqmapto_entries

代码语言:javascript
复制
bashjq '.users[] | {user: {name: .name, emails: .emails}}' input.json

但对于更复杂的扁平化需求,建议使用递归函数。

3. 使用递归函数进行深度扁平化

以下是一个通用的递归扁平化函数,适用于各种嵌套结构:

代码语言:javascript
复制
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 数据:

代码语言:javascript
复制
json{
  "a": 1,
  "b": {
    "c": 2,
    "d": [3, 4, {"e": 5}]
  },
  "f": [6, {"g": 7}]
}

应用上述 flatten 函数后,输出将为:

代码语言:javascript
复制
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
}

4. 综合示例

假设有以下 JSON 数据 input.json

代码语言:javascript
复制
json{
  "id": 1,
  "details": {
    "name": "张三",
    "contact": {
      "phone": "1234567890",
      "email": "zhangsan@example.com"
    }
  },
  "roles": ["admin", "user"]
}

要将其扁平化为:

代码语言:javascript
复制
json{
  "id": 1,
  "details.name": "张三",
  "details.contact.phone": "1234567890",
  "details.contact.email": "zhangsan@example.com",
  "roles[0]": "admin",
  "roles[1]": "user"
}

可以使用以下 jq 命令:

代码语言:javascript
复制
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

输出结果:​

代码语言:javascript
复制
json{
  "id": 1,
  "details.name": "张三",
  "details.contact.phone": "1234567890",
  "details.contact.email": "zhangsan@example.com",
  "roles[0]": "admin",
  "roles[1]": "user"
}
页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

领券