我有一个文件,其中每一行都是json(未格式化),如下所示:
{
"callID": "xxxxxxxxxxxxxx",
"authType": "xxxxxxxxxxxxxx",
"timestamp": "xxxxxxxxxxxxxx",
"errCode": "0",
"errMessage": "xxxxxxxxxxxxxx",
"endpoint": "xxxxxxxxxxxxxx",
"userKey": "xxxxxxxxxxxxxx",
"httpReq": {
"key1": "value1",
"key2": "value2",
"key3": "value3"
},
"ip": "xxxxxxxxxxxxxx",
"params": {
"key1": "value1",
"key2": "value2",
"key3": "value3"
},
"uid": "xxxxxxxxxxxxxx",
"apikey": "xxxxxxxxxxxxxx",
"userAgent": {
"key1": "value1",
"key2": "value2",
"key3": "value3"
},
"userKeyDetails": {
"name": "xxxxxxxxxxxxxx"
}
}
我需要执行转换,其中每个对象(httpReq
,params
,userAgent
,userKeyDetails
)都需要转换为对象数组,{{1 }}和key
属性。每个键不是强制性的,单个json可能没有所有给定的键。
这是结构的部分输出:
value
使用{
"httpReq": [
{
"key": "key1",
"value": "value1"
},
{
"key": "key2",
"value": "value2"
}
]
}
命令行,我了解jq
运算符是我要寻找的运算符,因此我创建了此命令
to_entries
它可以工作,但是在缺少给定键之一的行上失败,并显示以下错误:
cat test.json | jq -c '.userAgent = (.userAgent | to_entries) | .userKeyDetails = (.userKeyDetails | to_entries) | .params = (.params | to_entries) | .httpReq= (.
httpReq | to_entries)' > out.json
所以我需要一个选择器,该选择器可以处理丢失键的可能性,可以直接通过jq选择器获得吗?
答案 0 :(得分:4)
如果要对所有对象执行转换,则无需指定每个对象;以下应该可以解决问题。
map_values(if type == "object" then to_entries else . end)
答案 1 :(得分:0)
您的初始过滤器可以缩短为
(.userAgent |= to_entries) |
(.userKeyDetails |= to_entries) |
(.params |= to_entries) |
(.httpReq |= to_entries)
我们可以将常见行为抽象为一个函数:
def f(key):
.[key] |= to_entries
;
f("userAgent") | f("userKeyDetails") | f("params") | f("httpReq")
现在,我们只需要更新f
,以确保如果请求的密钥不存在,它也不会失败。为此,我们可以将.
替换为select(has(key))
。
def f(key):
select(has(key))[key] |= to_entries
;
f("userAgent") | f("userKeyDetails") | f("params") | f("httpReq")