【问题标题】:jq: Conditionally update/replace/add json elements using an input filejq:使用输入文件有条件地更新/替换/添加 json 元素
【发布时间】:2017-10-05 21:46:16
【问题描述】:

我收到以下输入文件:

  • input.json:
[
 {"ID":"aaa_12301248","time_CET":"00:00:00","VALUE":10,"FLAG":"0"},
 {"ID":"aaa_12301248","time_CET":"00:15:00","VALUE":18,"FLAG":"0"},
 {"ID":"aaa_12301248","time_CET":"00:30:00","VALUE":160,"FLAG":"0"},

 {"ID":"bbb_0021122","time_CET":"00:00:00","VALUE":null,"FLAG":"?"},
 {"ID":"bbb_0021122","time_CET":"00:15:00","VALUE":null,"FLAG":"?"},
 {"ID":"bbb_0021122","time_CET":"00:30:00","VALUE":22,"FLAG":"0"},

 {"ID":"ccc_0021122","time_CET":"00:00:00","VALUE":null,"FLAG":"?"},
 {"ID":"ccc_0021122","time_CET":"00:15:00","VALUE":null,"FLAG":"?"},
 {"ID":"ccc_0021122","time_CET":"00:30:00","VALUE":20,"FLAG":"0"},

 {"ID":"ddd_122455","time_CET":"00:00:00","VALUE":null,"FLAG":"?"},
 {"ID":"ddd_122455","time_CET":"00:15:00","VALUE":null,"FLAG":"?"},
 {"ID":"ddd_122455","time_CET":"00:30:00","VALUE":null,"FLAG":"?"},
]

如您所见,有一些有效值(FLAG:0)和一些无效值(FLAG:“?”)。 现在我得到了一个看起来像这样的文件(每个 ID 一个):

aaa.json:

[
  {"ID":"aaa_12301248","time_CET":"00:00:00","VALUE":10,"FLAG":"0"},
  {"ID":"aaa_12301248","time_CET":"00:15:00","VALUE":null,"FLAG":"?"},
  {"ID":"aaa_12301248","time_CET":"00:55:00","VALUE":45,"FLAG":"0"}
]

如您所见,对象一与 input.json 中的对象相同,但对象二无效(FLAG:“?”)。这就是为什么必须用 input.json 中的正确对象(使用 VALUE:18)替换对象 2 的原因。 对象可以通过“time_CET”和“ID”元素来识别。

此外,input.json 中还会有新的对象,这些对象不是 aaa.json 等的一部分。这些对象应该添加到数组中,并且应该保留 aaa.json 中的有效对象。

最后,aaa.json 应该是这样的:

[
  {"ID":"aaa_12301248","time_CET":"00:00:00","VALUE":10,"FLAG":"0"},
  {"ID":"aaa_12301248","time_CET":"00:15:00","VALUE":18,"FLAG":"0"},
  {"ID":"aaa_12301248","time_CET":"00:30:00","VALUE":160,"FLAG":"0"},
  {"ID":"aaa_12301248","time_CET":"00:55:00","VALUE":45,"FLAG":"0"}
]

所以,总结一下:

  1. 寻找标志:“?”在 aaa.json 中
  2. 使用“ID”将这个对象替换为来自 input.json 的匹配对象 和“time_CET”用于映射。
  3. 保持现有的有效对象并从 input.json 添加对象 之前在 aaa.json 中不存在(这意味着只有对象开始 在“ID”字段中带有“aaa”)
  4. 对 bbb.json、ccc.json 和 ddd.json 重复此操作

我不确定是否可以使用这样的命令一次完成所有操作,因为输出必须返回到正确的 id 文件(aaa、bbb ccc.json):

jq --argfile aaa aaa.json --argfile bbb bbb.json .... -f prog.jq input.json

问题是,标识符后面的数字(aaa、bbb、ccc 等)可能会改变。因此,要确保将对象添加到正确的文件/数组中,需要这样的语句:
if (."ID"|contains("aaa")) then ....

还是用不同的输入参数多次运行程序更好?我不确定..

提前谢谢你!!

【问题讨论】:

    标签: json jq


    【解决方案1】:

    这是一种方法

    #!/bin/bash
    
    # usage: update.sh input.json aaa.json bbb.json....
    # updates each of aaa.json bbb.json.... 
    
    input_json="$1"
    shift
    
    for i in "$@"; do
        jq -M --argfile input_json "$input_json" '
    
          # functions to restrict input.json to keys of current xxx.json file
          def prefix:              input_filename | split(".")[0];
          def selectprefix:        select(.ID | startswith(prefix));
    
          # functions to build and probe a lookup table
          def pk:                  [.ID, .time_CET];
          def lookup($t;$k):       $t | getpath($k);
          def lookup($t):          lookup($t;pk);
          def organize(s):         reduce s as $r ({}; setpath($r|pk; $r));
    
          # functions to identify objects in input.json missing from xxx.json
          def pks:                 paths | select(length==2);
          def missing($t1;$t2):    [$t1|pks] - [$t2|pks] | .[];
          def getmissing($t1;$t2): [ missing($t1;$t2) as $p | lookup($t1;$p)];
    
          # main routine
            organize(.[]) as $xxx
          | organize($input_json[] | selectprefix) as $inp
          | map(if .FLAG != "?" then . else . += lookup($inp) end)
          | . + getmissing($inp;$xxx)
    
        ' "$i" | sponge "$i"
    
    done
    

    脚本在循环中使用 jq 来读取和更新每个 aaa.json... 文件。

    过滤器创建临时对象以方便[ID,time_CET] 查找值,使用 FLAG=="?" 更新 aaa.json 中的任何值最后添加 input.jsonaaa.json 中缺少的任何值。

    input.json 的临时查找表使用 input_filename,因此只会包含以与当前处理的文件名称匹配的前缀开头的键。

    示例运行:

    $ ./update.sh input.json aaa.json
    

    aaa.json 运行后:

    [
      {
        "ID": "aaa_12301248",
        "time_CET": "00:00:00",
        "VALUE": 10,
        "FLAG": "0"
      },
      {
        "ID": "aaa_12301248",
        "time_CET": "00:15:00",
        "VALUE": 18,
        "FLAG": "0"
      },
      {
        "ID": "aaa_12301248",
        "time_CET": "00:55:00",
        "VALUE": 45,
        "FLAG": "0"
      },
      {
        "ID": "aaa_12301248",
        "time_CET": "00:30:00",
        "VALUE": 160,
        "FLAG": "0"
      }
    ]
    

    【讨论】:

    • 嗨!感谢您的回答。它适用于样本。但是,如果要添加多个对象,它会创建一个全新的数组,并且不会将其添加到 aaa.json 的初始数组中。只需将此行添加到 input.json 中,您将看到:'{"ID":"aaa_0021122","time_CET":"00:45:00","VALUE":22,"FLAG":"?"}, ' 我只想要 aaa/bbb/ccc.json 文件中的一个数组,而不是每个添加的对象一个数组。到目前为止谢谢!
    • 我明白了。我在getmissing 的定义中的错误位置有一个[。这个版本应该可以工作。作为一个学习练习,你可能想看看你是否能弄清楚为什么将数组构造函数的开头放在这个特定的地方会产生这样的效果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-03
    • 1970-01-01
    • 2019-01-17
    • 2020-01-26
    相关资源
    最近更新 更多