在特定位置添加JSON对象

问题描述 投票:0回答:2

这是我的两个json文件内容:

file1.json

{
  "nodes": [
    {
      "pm_addr": "192.100.0.4",
      "name": "TB1-OSC-A"
    },
    {
      "pm_addr": "192.100.0.6",
      "name": "TB1-OSC-B"
    },
    {
      "pm_addr": "192.100.0.7",
      "name": "TB1-OSC-C"
    }
  ]
}

file2.json

{
  "nodes": [
    {
      "pm_addr": "192.100.0.4",
      "name": "TB1-OSC-D"
    }
  ]
}

我想将file2.json的内容添加到file1.json,但在json对象之后:TB1-OSC-B,即第二个json条目。在这种情况下,该条目位于第二位置,但也可以位于其他任何位置。我的最终json文件应如下所示:

file3.json

{
  "nodes": [
    {
      "pm_addr": "192.100.0.4",
      "name": "TB1-OSC-A"
    },
    {
      "pm_addr": "192.100.0.6",
      "name": "TB1-OSC-B"
    },
    {
      "pm_addr": "192.100.0.4",
      "name": "TB1-OSC-D"
    },
    {
      "pm_addr": "192.100.0.7",
      "name": "TB1-OSC-C"
    }
  ]
}

我使用的是jq版本:1.3,我无法对其进行升级。我尝试使用jq提供的add和= +参数。但这没有帮助。

感谢进阶

json linux jq
2个回答
2
投票

如果要将对象从file2.json附加到nodes数组,则非常简单:

jq -s '.[0].nodes += [ .[1].nodes[0] ] | .[0]' file1.json file2.json

输出:

{
  "nodes": [
    {
      "pm_addr": "192.100.0.4",
      "name": "TB1-OSC-A"
    },
    {
      "pm_addr": "192.100.0.6",
      "name": "TB1-OSC-B"
    },
    {
      "pm_addr": "192.100.0.7",
      "name": "TB1-OSC-C"
    },
    {
      "pm_addr": "192.100.0.4",
      "name": "TB1-OSC-D"
    }
  ]
}

但是,由于要插入对象,因此变得更加棘手,因为jq AFAIK不支持插入数组,仅支持前置和追加。

下面是一个相当复杂的示例,说明了如何通过将其拼接在其中:

parse.jq

# Find the desired index and store it as $n
(.[0].nodes | map(.name == "TB1-OSC-B") | index(true)) as $n   |

# Splice the object from the second file  into the first
.[0].nodes =   .[0].nodes[0:($n|tonumber+1)]   +
             [ .[1].nodes[0] ]                 +
               .[0].nodes[($n|tonumber+1):(.[0].nodes|length)] |

# Only output the now modified object from the first file 
.[0]

像这样运行它:

jq -sf parse.jq file1.json file2.json

在这种情况下的输出:

{
  "nodes": [
    {
      "pm_addr": "192.100.0.4",
      "name": "TB1-OSC-A"
    },
    {
      "pm_addr": "192.100.0.6",
      "name": "TB1-OSC-B"
    },
    {
      "pm_addr": "192.100.0.4",
      "name": "TB1-OSC-D"
    },
    {
      "pm_addr": "192.100.0.7",
      "name": "TB1-OSC-C"
    }
  ]
}

0
投票

清晰,可维护的解决方案的关键是具有适当的实用程序功能。

jq 1.3的实用程序功能

def insert_at(i; x): .[:i] + [x] + .[i:];

def indicesof(f):
  . as $in
  | range(0;length) | select( $in[.] | f );

def insert_after(f; x):
  [indicesof(f)] as $ix
  | if ($ix|length) > 0
    then insert_at($ix[0]+1; x) 
    else . end;

jq 1.4或更高版本的实用程序功能

jq 1.4允许更有效的解决方案,first/1

def insert_at($i; $x): .[:$i] + [$x] + .[$i:];

def indicesof(f):
  . as $in
  | range(0;length) | select( $in[.] | f );

def insert_after(f; $x):
  (first(indicesof(f)) // null) as $i
  | if $i then insert_at($i + 1; $x) else . end;

解决方案

使用这些实用程序功能,可以直接表达给定问题的解决方案。例如,假设调用如下:

jq -s -f merge.jq file1.json file2.json

.[1].nodes[0] as $file2
| .[0]
| .nodes |= insert_after(.name == "TB1-OSC-B"; $file2)

可以根据详细要求轻松进行修改。

© www.soinside.com 2019 - 2024. All rights reserved.