简体   繁体   English

如何在jq中使用父object数据提取和修改内部数组对象

[英]how to extract and modify inner array objects with parent object data in jq

We are tying to format a json similar to this:我们正在尝试格式化 json,类似于:

[
{"id": 1,
    "type": "A",
    "changes": [ 
        {"id": 12},
        {"id": 13}
    ],
    "wanted_key": "good",
    "unwanted_key": "aaa"
},
{"id": 2,
    "type": "A",
    "unwanted_key": "aaa"
},
{"id": 3,
    "type": "B",
    "changes": [
        {"id": 31},
        {"id": 32}
    ],
    "unwanted_key": "aaa",
    "unwanted_key2": "aaa"
},
{"id": 4,
    "type": "B",
    "unwanted_key3": "aaa"
},
null,
null,
{"id": 7}
]

into something like this:变成这样的东西:

[
  {
    "id": 1,
    "type": "A",
    "wanted_key": true  # every record must have this key/value
  },
  {
    "id": 12,  # note: this was in the "changes" property of record id 1
    "type": "A",  # type should be the same type than record id 1
    "wanted_key": true
  },
  {
    "id": 13,  # note: this was in the "changes" property of record id 1
    "type": "A",  # type should be the same type than record id 1
    "wanted_key": true
  },
  {
    "id": 2,
    "type": "A",
    "wanted_key": true
  },
  {
    "id": 3,
    "type": "B",
    "wanted_key": true
  },
  {
    "id": 31,  # note: this was in the "changes" property of record id 3
    "type": "B",  # type should be the same type than record id 3
    "wanted_key": true
  },
  {
    "id": 32,  # note: this was in the "changes" property of record id 3
    "type": "B",  # type should be the same type than record id 3
    "wanted_key": true
  },
  {
    "id": 4,
    "type": "B",
    "wanted_key": true
  },
  {
    "id": 7,
    "type": "UNKN",  # records without a type should have this type
    "wanted_key": true
  }
]

So far, I've been able to:到目前为止,我已经能够:

  • remove null records删除 null 记录
  • obtain the keys we need with their default获取我们需要的默认密钥
  • give records without a type a default type给没有类型的记录一个默认类型

What we are missing:我们缺少什么:

  • from records having a changes key, create new records with the type of their parent record从具有changes键的记录中,创建具有其父记录type的新记录
  • join all records in a single array将所有记录连接到一个数组中

Unfortunately we are not entirely sure how to proceed... Any help would be appreciated.不幸的是,我们不完全确定如何进行......任何帮助将不胜感激。

So far our jq goes like this: del(..|nulls) | map({id, type: (.type // "UNKN"), wanted_key: (true)}) | del(..|nulls)到目前为止,我们的 jq 是这样的: del(..|nulls) | map({id, type: (.type // "UNKN"), wanted_key: (true)}) | del(..|nulls) del(..|nulls) | map({id, type: (.type // "UNKN"), wanted_key: (true)}) | del(..|nulls)

Here's our test code:这是我们的测试代码:

https://jqplay.org/s/eLAWwP1ha8P https://jqplay.org/s/eLAWwP1ha8P

The following should work:以下应该有效:

map(select(values))
| map(., .type as $type | (.changes[]? + {$type}))
| map({id, type: (.type // "UNKN"), wanted_key: true})
  1. Only select non-null values只有 select 非空值
  2. Return the original items followed by their inner changes array (+ outer type)返回原始项目,后跟它们的内部更改数组(+ 外部类型)
  3. Extract 3 properties for output提取 output 的 3 个属性

Multiple map calls can usually be combined, so this becomes:多个map调用通常可以组合起来,因此变为:

map(
    select(values)
    | ., (.type as $type | (.changes[]? + {$type}))
    | {id, type: (.type // "UNKN"), wanted_key: true}
)

Another option without variables:没有变量的另一个选项:

map(
    select(values)
    | ., .changes[]? + {type}
    | {id, type: (.type // "UNKN"), wanted_key: true}
)
# or:
map(select(values))
| map(., .changes[]? + {type})
| map({id, type: (.type // "UNKN"), wanted_key: true})

or even with a separate normalization step for the unknown type:甚至对未知类型有一个单独的标准化步骤:

map(select(values))
| map(.type //= "UNKN")
| map(., .changes[]? + {type})
| map({id, type, wanted_key: true})
# condensed to a single line:
map(select(values) | .type //= "UNKN" | ., .changes[]? + {type} | {id, type, wanted_key: true})

Explanation:解释:

  1. Select only non-null values from the array Select 仅来自数组的非空值
  2. If type is not set, create the property with value "UNKN"如果未设置类型,则创建值为"UNKN"的属性
  3. Produce the original array items, followed by their nested changes elements extended with the parent type生成原始数组项,然后是使用父类型扩展的嵌套更改元素
  4. Reshape objects to only contain properties id, type, and wanted_key.重塑对象以仅包含属性 id、type 和 Wanted_key。

Here's one way:这是一种方法:

map(
  select(values)
  | (.type // "UNKN") as $type
  | ., .changes[]?
  | {id, $type, wanted_key: true}
)
[
  {
    "id": 1,
    "type": "A",
    "wanted_key": true
  },
  {
    "id": 12,
    "type": "A",
    "wanted_key": true
  },
  {
    "id": 13,
    "type": "A",
    "wanted_key": true
  },
  {
    "id": 2,
    "type": "A",
    "wanted_key": true
  },
  {
    "id": 3,
    "type": "B",
    "wanted_key": true
  },
  {
    "id": 31,
    "type": "B",
    "wanted_key": true
  },
  {
    "id": 32,
    "type": "B",
    "wanted_key": true
  },
  {
    "id": 4,
    "type": "B",
    "wanted_key": true
  },
  {
    "id": 7,
    "type": "UNKN",
    "wanted_key": true
  }
]

Demo演示

Something like below should work像下面这样的东西应该工作

map( 
  select(type == "object") | 
  ( {id}, {id : ( .changes[]? .id )} ) + 
  { type: (.type // "UNKN"), wanted_key: true }
)

jq play - demo jq play -演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM