如何合并两个JSON对象

vpfxa7rd  于 2023-08-08  发布在  其他
关注(0)|答案(3)|浏览(103)

我想合并两个具有公共键的JSON对象
对象A

{
  "extensions": { 
    "app_name": "extensions-prod"
  },
  "plugins": { 
    "app_name": "plugins-prod" 
  }
}

字符串
对象B

{
  "plugins": { 
    "project_name": "plugins-prod" 
  }
}


所需输出:

{
  "plugins": { 
    "project_name": "plugins-prod",
    "app_name": "plugins-prod" 
  }
}


我确实研究了其他的SO posts,但不是很有用,因为我的结构是不同的。json对象也是bash变量,不包含在文件中。
[编辑]我不知道公共密钥是什么,因为JSON对象是在CI环境中动态生成的。

piok6c0g

piok6c0g1#

[编辑]我不知道公共密钥是什么
使用in,您可以找出给定对象中是否存在给定的键。因此,您可以使用with_entries来迭代对象的字段,而select(保留)仅保留其.key存在于另一个对象中的那些条目。如果对象A以这种方式被“修剪”,则可以使用*将其(深度)合并到对象B中:

jq -n --argjson objA "$objA" --argjson objB "$objB" \
  '$objB * ($objA | with_entries(select(.key | in($objB))))'

字符串
这假设(根据您的示例数据)对象B只包含公共键,因此只有对象A必须被修剪为对象B的键。如果通常不是这样,那么用物体A对称地处理物体B。事实上,你可以在一个可参数化的函数中定义修剪,并在两个对象上相互使用它:

jq -n --argjson objA "$objA" --argjson objB "$objB" '
  def trim_to($o): with_entries(select(.key | in($o)));
  ($objB | trim_to($objA)) * ($objA | trim_to($objB))
'


给定样本数据,两个输出:

{
  "plugins": {
    "project_name": "plugins-prod",
    "app_name": "plugins-prod"
  }
}

3htmauhk

3htmauhk2#

下面的解决方案不假设键名的交集是单例

jq -n --argjson a "$A" --argjson b "$B" '

  def i: (.[0] | unique) as $u | $u - ($u - .[1]); 
  def k: [$a, $b] | map(keys_unsorted) | i;
  [k[] | { (.): ($b[.] + $a[.]) } ] | add
'

字符串

t3psigkw

t3psigkw3#

这应该达到预期的效果:

#!/usr/bin/env bash

A='{
  "extensions": { 
    "app_name": "extensions-prod"
  },
  "plugins": { 
    "app_name": "plugins-prod" 
  }
}'
B='
{
  "plugins": { 
    "project_name": "plugins-prod" 
  }
}'

jq -s 'map(to_entries) |
       add |
       group_by(.key) |
       map(select(length == 2) |
           { key: first | .key,
             value: map(.value) | add
           }
          ) |
       from_entries' <<< "$A $B"

字符串

相关问题