简体   繁体   English

jq操作json文件

[英]jq to manipulate a json file

Having as input below sample json: 作为输入示例json下面:

{
    "name_A": {
        "logfile_one": [{
            "issue_desc": "desiredvalueone"
        }, {
            "issuetime": "desiredvaluetwo"
        }],
        "output": ["46312"]
    },
    "name_B": {
        "logfile_two": [{
            "issue_desc": "desiredvaluethirtyfour"
        }, {
            "issuetime": "desiredvaluetwo"
        }],
        "output": ["1", "2"]
    }
}

We would like the following output: 我们想要以下输出:

{
    "desiredvalueone": [{
        "name_A": "logfile_one"
    }],
    "desiredvaluetwo": [{
        "name_A": "logfile_one",
        "name_B": "logfile_two"
    }],
    ...
}

using t o_entries[] | .key 使用t o_entries[] | .key o_entries[] | .key for instance, we manage to get " name_A " " name_B ", but very far from what we try to achieve. o_entries[] | .key为例,我们设法获得“ name_A ”和“ name_B ”,但与我们试图达到的目标相去甚远。 Or with 或搭配

[to_entries[] | {"key": .key, "value": .value[]}] | from_entries

output was 输出是

{
  "name_A": [
    "46312"
  ],
  "name_B": [
    "1",
    "2"
  ]
}

The .... in the given expected output introduces several uncertainties beyond those in the problem statement itself, but the following program does produce results that are consistent with the expected output as shown. 给定预期输出中的....引入了一些问题,这些不确定性超出了问题陈述本身的不确定性,但是下面的程序的确产生与预期输出一致的结果,如图所示。

The key to the solution given here is the helper function for combining a stream of JSON objects: 此处给出的解决方案的关键是用于组合JSON对象流的辅助函数:

# Combine a stream of JSON objects into a single object
# by converting the value v to [v] at each
# key, and then appending the arrays at each key.
def combine(s):
  reduce s as $o ({};
    reduce ($o|keys[]) as $k (.; .[$k] += [$o[$k]]  ) );

The problem as I understand it can now be solved using to_entries/0 three times; 据我了解,现在可以使用to_entries/0三次解决该问题; if you're not familiar with that filter, the following might seem fairly incomprehensible: 如果您不熟悉该过滤器,则以下内容可能会让人难以理解:

combine( to_entries[]
   | .key as $k
   | .value
   | to_entries[]
   | select( .key | startswith("logfile_"))
   | .key as $innerkey
   | .value[]
   | to_entries[]
   | { (.value): { ($k): $innerkey }}
 ) | map_values(add)

The output with the given input is: 给定输入的输出为:

{
  "desiredvalueone": {
    "name_A": "logfile_one"
  },
  "desiredvaluetwo": {
    "name_A": "logfile_one",
    "name_B": "logfile_two"
  },
  "desiredvaluethirtyfour": {
    "name_B": "logfile_two"
  }
}

Here is a solution which only assumes the input has the following structure 这是一个仅假定输入具有以下结构的解决方案

{ 
  "k": {
     "k2": [{
        "k3": "v"

It works by generating a temporary array of objects of the format 它通过生成以下格式的对象的临时数组来工作

{"v":"desiredvalueone","k":"name_A","k2":"logfile_one"}

then grouping by .v and combining groups and wrapping values in an array as requested. 然后按.v分组,并根据要求组合组和将值包装在数组中。

[
  . as $d
| [
      keys[] as $k                           # e.g "name_A"...
    | ($d[$k] | keys[]
       | select($d[$k][.][0]|type=="object")
       ) as $k2                              # k2:  "logfile_one"
    | $d[$k][$k2][] as $v                    # v:  {"issue_desc":"desiredvalueone"},
    | ($v|keys[]) as $k3                     # k3: "issue_desc"
    | {v:$v[$k3], k:$k, k2:$k2}              # {"v":"desiredvalueone","k":"name_A","k2":"logfile_one"}
  ]
| group_by(.v)[]
| reduce .[] as $t (
    {}
  ; .[$t.v] += {($t.k): $t.k2}
  )
]
| add
| map_values([.])

The final output is 最终输出是

{
  "desiredvalueone": [
    {
      "name_A": "logfile_one"
    }
  ],
  "desiredvaluethirtyfour": [
    {
      "name_B": "logfile_two"
    }
  ],
  "desiredvaluetwo": [
    {
      "name_A": "logfile_one",
      "name_B": "logfile_two"
    }
  ]
}

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

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