如何在jq中提取和修改带有父对象数据的内部数组对象



我们正在绑定一个类似于以下的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}
]

变成这样:

[
{
"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
}
]

到目前为止,我已经能够:

  • 删除空记录
  • 获取我们需要的默认密钥
  • 为没有类型的记录指定默认类型

我们缺少的是:

  • 从具有changes密钥的记录中,使用其父记录的type创建新记录
  • 将所有记录连接到一个数组中

不幸的是,我们不完全确定如何继续。。。如有任何帮助,我们将不胜感激。

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

这是我们的测试代码:

https://jqplay.org/s/eLAWwP1ha8P

以下内容应该有效:

map(select(values))
| map(., .type as $type | (.changes[]? + {$type}))
| map({id, type: (.type // "UNKN"), wanted_key: true})
  1. 仅选择非null值
  2. 返回原始项及其内部更改数组(+外部类型(
  3. 提取3个属性进行输出

通常可以组合多个map调用,因此这变成:

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

另一个没有变量的选项:

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})

或者甚至对未知类型进行单独的归一化步骤:

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})

说明:

  1. 只从数组中选择非null值
  2. 如果未设置类型,则创建值为"UNKN"的特性
  3. 生成原始数组项,然后生成用父类型扩展的嵌套更改元素
  4. 将对象重塑为只包含属性id、类型和wanted_key

这里有一种方法:

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
}
]

演示

下面这样的东西应该能在中工作

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

jq播放-演示

最新更新