jq:生成JSON:动态密钥创建可能吗?

时间:2016-02-12 23:29:35

标签: bash variables jq

我从未使用jq生成JSON,只解析。所以这对我来说是不成熟的领域。

我找到jq & bash: make JSON array from variable,这让我更接近我所寻求的。但是,我还没有确定如何为我正在寻找的结构动态创建关键名称。

我寻求的结构看起来像这样:

{
  "eth0":
        {
            "key1": "value1",
            "key2": "value2",
            "key3": "value3"
        },
  "eth3":
        {
            "key1": "value1",
            "key2": "value2",
            "key3": "value3"
        }
}

派生自csv:

iface,key1,key2,key3
eth0,value1,value2,value3
eth3,value1,value2,value3

我遇到的问题是从CSV动态生成JSON中的密钥。我还没有找到jq这样做的能力。我使用的是jq 1.5。

我是否在转动轮子?

编辑 - 可能的答案

目前正在调查这本食谱的答案:

https://github.com/stedolan/jq/wiki/Cookbook#convert-a-csv-file-with-headers-to-json

2 个答案:

答案 0 :(得分:1)

理想情况下,您的输入应该是JSON,因此您应该通过可以将CSV文件转换为包含数据的数组的文件来运行文件,以便jq可以使用它。假设您的数据不复杂且值本身不会包含逗号,您可以读取原始行并拆分它们。那么这只是建立你的结果的问题。

$ jq -R 'split(",") as $k |
    reduce (inputs | split(",")) as $r ({};
        .[$r[0]] = ([range(1;$k|length) | { key: $k[.], value: $r[.] }] | from_entries)
    )' input.csv

答案 1 :(得分:1)

这是一个直接的解决方案,实际上非常类似于Jeff(特别是,它对CSV做出了相同的假设),但它使用input表示第一行,inputs表示其余部分行,jq Cookbook中的“objectify”的简化版本,以及主过滤器中的add而不是reduce

jq -R -n '
  def objectify(headers): . as $in
    | reduce range(0; headers|length) as $i
        ({}; .[headers[$i]] = $in[$i]  );

  ((input|split(","))[1:]) as $headers
  | [ (inputs|split(",")) as $line
      | { ($line[0]): ($line[1:] | objectify($headers)) } ]
  | add
'