根据匹配的字段从另一个JSON文件添加或更新一个JSON文件中的字段

时间:2019-07-02 08:03:49

标签: json jq

我有两个JSON文件a.jsonb.json。 a.json文件中的内容是一个JSON对象,b.json中的内容是一个数组。我想通过从b中检索值来在a.json中的每个status中添加/更新mappings字段。 json文件。
a.json:

{
  "title": 25886,
  "data": {
    "request": {
      "c": 46369,
      "t1": 1562050127.376641
    },
  },
  "rs": {
    "mappings": {
      "12345": {
        "id": "12345",
        "name": "test",
        "customer_id": "11228",
      },
      "45678": {
        "id": "45678",
        "name": "abc",
        "customer_id": "11206",
      }
    }
}}

b.json:

[
  {
    "status": "pending",
    "extra": {
      "name": "test"
    },
    "enabled": true,
    "id": "12345"
  },
  {
    "status": "not_started",
    "extra": {
      "name": "abc"
    },
    "enabled": true,
    "id": "45678"
  }
]

以下是我的预期输出:

{
  "title": 25886,
  "data": {
    "request": {
      "c": 46369,
      "t1": 1562050127.376641
    },
  },
  "rs": {
    "mappings": {
      "12345": {
        "id": "12345",
        "name": "test",
        "customer_id": "11228",
        "status":"pending"
      },
      "45678": {
        "id": "45678",
        "name": "abc",
        "customer_id": "11206",
        "status":"not_started"
      }
    }
}}

在这个预期的JSON文件中,我们有status字段,该字段的值基于匹配的id值从b.json文件中检索。如何使用jq来做到这一点?

2 个答案:

答案 0 :(得分:0)

出于这个问题的目的,b.json本质上定义了一个字典,因此为了简单,高效甚至优雅起见, 首先,请使用内置函数INDEX创建相关的字典:

INDEX( $b[] | {id, status}; .id )

这假设调用jq的方式如下:

jq --argfile b b.json -f update.jq a.json

(是的,我知道--argfile已被弃用。请随意选择另一种将$ b设置为b.json内容的方法。)

现在,要执行更新,最简单的方法是将{update}运算符|=map_values结合使用。 (随时查看jq手册:-)

将所有内容放在一起:

INDEX( $b[] | {id, status}; .id ) as $dict
| .rs.mappings |= map_values( .status = $dict[.id].status )

答案 1 :(得分:0)

使用基于步行路径的unix实用程序 jtc

可以轻松实现相同的JSON操作:
bash $ <a.json jtc -w'<id>l:<ID>v[-1]' -i b.json -i'<ID>s[-1][status]'
{
   "data": {
      "request": {
         "c": 46369,
         "t1": 1562050127.376641
      }
   },
   "rs": {
      "mappings": {
         "12345": {
            "customer_id": "11228",
            "id": "12345",
            "name": "test",
            "status": "pending"
         },
         "45678": {
            "customer_id": "11206",
            "id": "45678",
            "name": "abc",
            "status": "not_started"
         }
      }
   },
   "title": 25886
}
bash $ 
  • 目的地在此处(-w,要插入新记录的地方)递归查找每个标签id<id>l:),并在命名空间ID中存储条目(<ID>v)并后退1级,以指向父条目
  • 对于每个目标遍历(-w),都会有一个相应的插入遍历(第二个-i,第一个指向用于插入的源文件);插入遍历将找到(在b.json中)存储在名称空间ID中的值,提升一级并选择status记录,将其插入

PS>披露:我是jtc-用于JSON操作的shell cli工具的创建者