简体   繁体   English

将对象转换为键值对数组

[英]Convert objects to arrays of key-value pairs

I have a file where every line is a json (not formatted) as follows:我有一个文件,其中每一行都是一个 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"
  }
}

I need to perform a conversion where every object ( httpReq , params , userAgent , userKeyDetails ) need to be converted as array of objects, with key and value properties.我需要执行一个转换,其中每个对象( httpReqparamsuserAgentuserKeyDetails )都需要转换为具有keyvalue属性的对象数组。 Every key is not mandatory, a single json may NOT have all given keys.每个键都不是强制性的,单个 json 可能没有所有给定的键。

Here is a partial output of the structure:这是结构的部分输出:

{
  "httpReq": [
    {
      "key": "key1",
      "value": "value1"
    },
    {
      "key": "key2",
      "value": "value2"
    }
  ]
}

Using jq command line I understand that to_entries operator is the one I'm looking for, so I created this command使用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

It works, but it's failing on rows where one of the given key is missing, with following error:它可以工作,但是在缺少给定键之一的行上失败,并出现以下错误:

jq: error (at <stdin>:2): null (null) has no keys
jq: error (at <stdin>:3): null (null) has no keys
jq: error (at <stdin>:4): null (null) has no keys
jq: error (at <stdin>:5): null (null) has no keys

So I need a selector which works handling the possibility of a key to be missing, can this be obtained directly with a jq selector?所以我需要一个选择器来处理丢失键的可能性,这可以直接用 jq 选择器获得吗?

If you want to perform the conversion on all the objects you don't need to specify every one of them;如果要对所有对象执行转换,则无需指定每个对象; following should do the trick.以下应该可以解决问题。

map_values(if type == "object" then to_entries else . end)

REPL demo REPL 演示

Your initial filter can be shortened to您的初始过滤器可以缩短为

(.userAgent |= to_entries) |
(.userKeyDetails |= to_entries) | 
(.params |= to_entries) | 
(.httpReq |= to_entries)

and we can abstract the common behavior to a function:我们可以将常见行为抽象为一个函数:

def f(key):
  .[key] |= to_entries
;
f("userAgent") | f("userKeyDetails") | f("params") | f("httpReq")

Now we just need to update f so that it doesn't fail if the requested key doesn't exist.现在我们只需要更新f以便在请求的密钥不存在时它不会失败。 To do that, we can replace .为此,我们可以替换. with select(has(key)) .select(has(key))

def f(key):
    select(has(key))[key] |= to_entries
;
f("userAgent") | f("userKeyDetails") | f("params") | f("httpReq")

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

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