在现有 json 元素中添加新的键值对

Adding new key-value pair in an existing json element

我有一个基本上从 XML 生成 JSON 的 perl 脚本。这部分工作正常。但是在完成一些业务逻辑之后,我需要向 JSON.

中的现有元素添加一个新的键值对

我可以在 JSON 中插入一个全新的元素,但不能在输入 JSON 的现有元素中插入键值对。

这是示例 JSON:

{
    "Person": {
       "ID": "0", 
       "SchemaVersion": "1.0.8", 
       "Home": {
          "ID": "ABC-XYZ", 

          "Laptop": {
             "FileName": "/usr/temp/RPM_020515_.tar.gz"
           }, 

          "Location": {
              "Number": "62", 
              "MaxSize": "0", 
              "Comment": { }, 
              "SiteName": { }
           }, 

          "State": "Unknown"
       }
    }
 }

现在在上面 json 我试图在元素笔记本电脑 (Person->Home->Laptop) 下添加一个基于某些业务逻辑生成的新键值对。 (键值对示例:"Key":"123456789"),所以新 JSON 看起来像这样:

{
    "Person": {
       "ID": "0", 
       "SchemaVersion": "1.0.8", 
       "Home": {
          "ID": "ABC-XYZ", 

          "Laptop": {
             "FileName": "/usr/temp/RPM_020515_.tar.gz",
             "Key": "123456789"
           }, 

          "Location": {
              "Number": "62", 
              "MaxSize": "0", 
              "Comment": { }, 
              "SiteName": { }
           }, 

          "State": "Unknown"
       }
    }
 }

我在 perl 代码中采用的方法是:

  1. 首先将 JSON 转换为哈希映射
  2. 正在尝试添加新元素(这是出现问题的地方,我可以添加一个全新的元素,但不能在现有元素中添加键值对)
  3. 将哈希映射转换回 JSON。

相同的 Perl 代码:(忽略任何缺少的 use 语句,使脚本不那么复杂只是为了突出显示错误)

 #!/usr/bin/perl
 use strict;
 use warnings FATAL => qw( all );
 use Data::Dumper;

 use JSON;

# get back the original JSON into a hashmap (key value pairs)
 ( $json is output of JSON generated from an XML file but for this example 
   please use the sample JSON i have mentioned above )
my $tempHash = decode_json($json);  

# new key-value pair that needs to be added in the JSON ( in original code   
  it is being generated from business logic but in similar format )
 %filedata = ('Key', 123456789);

# insert the fileKey now. Think about how to insert the file key here
push @{ $tempHash->{'Person'}->{'Home'}->{'Laptop'}}, $\%fileData; 

my $newJSON =  encode_json($tempHash);

上面的代码没有像我预期的那样工作。 它实际上是通过创建新元素 {'Person'}->{'Home'}->{'Laptop'}} 添加键值对,而不是将它们添加到现有元素下(这是预期行为)。

有人可以指出我正确的语法或任何其他建议。

我已经尝试以非常简单的方式解释这个问题(原来的代码现在变得非常复杂并且做了很多不同的事情)。让我知道是否需要更多细节或我为解决问题所做的研究需要更多信息。

直接设置键和值会更有意义。 JSON 的笔记本电脑部分 不是 数组,因此您不能将元素推入其中:

use strict;
use warnings;

use Data::Dumper;
use JSON;


my $json;
{
   local $/;
   $json = from_json( <DATA> );
}

$json->{Person}->{Home}->{Laptop}->{Key} = 123456789;
print Dumper $json;

__DATA__
{
   "Person": {
      "ID": "0", 
      "SchemaVersion": "1.0.8", 
       "Home": {
          "ID": "ABC-XYZ", 

          "Laptop": {
             "FileName": "/usr/temp/RPM_020515_.tar.gz"
           }, 

          "Location": {
              "Number": "62", 
              "MaxSize": "0", 
              "Comment": { }, 
              "SiteName": { }
           }, 

          "State": "Unknown"
       }
    }
}

我会使用:

use strict;
use warnings;

use JSON;
use Hash::Merge qw(merge);

my $wantadd->{Person}->{Home}->{Laptop} = {
    key => 123456,
    some => 'data1',
    other => 'data2',
    deeper => {
        deep1 => "deep1",
        deep2 => "deep2",
    },
};

my $json_str = do { local $/; <DATA> };
my $json = JSON->new();

my $tempHash = $json->decode($json_str);  
my $newhash = merge($tempHash,$wantadd);
print $json->pretty->encode($newhash);

#or in compact form
print encode_json(merge(decode_json($json_str),$wantadd));

__DATA__
{
   "Person" : {
      "ID" : "0",
      "SchemaVersion" : "1.0.8",
      "Home" : {
         "State" : "Unknown",
         "Laptop" : {
            "FileName" : "/usr/temp/RPM_020515_.tar.gz"
         },
         "Location" : {
            "MaxSize" : "0",
            "Comment" : {},
            "SiteName" : {},
            "Number" : "62"
         },
         "ID" : "ABC-XYZ"
      }
   }
}

它打印:

{
   "Person" : {
      "ID" : "0",
      "Home" : {
         "ID" : "ABC-XYZ",
         "Location" : {
            "MaxSize" : "0",
            "SiteName" : {},
            "Number" : "62",
            "Comment" : {}
         },
         "State" : "Unknown",
         "Laptop" : {
            "FileName" : "/usr/temp/RPM_020515_.tar.gz",
            "key" : 123456,
            "other" : "data2",
            "deeper" : {
               "deep1" : "deep1",
               "deep2" : "deep2"
            },
            "some" : "data1"
         }
      },
      "SchemaVersion" : "1.0.8"
   }
}

{"Person":{"SchemaVersion":"1.0.8","Home":{"ID":"ABC-XYZ","Laptop":{"key":123456,"FileName":"/usr/temp/RPM_020515_.tar.gz","some":"data1","deeper":{"deep1":"deep1","deep2":"deep2"},"other":"data2"},"State":"Unknown","Location":{"MaxSize":"0","SiteName":{},"Number":"62","Comment":{}}},"ID":"0"}}

将新数据添加到所需位置。

而不是你的台词

 %filedata = ('Key', 123456789);

 # insert the fileKey now. Think about how to insert the file key here
 push @{ $tempHash->{'Person'}->{'Home'}->{'Laptop'}}, $\%fileData;

使用线条

my ($key, $val) = ('Key', 123456789);
$tempHash->{'Person'}->{'Home'}->{'Laptop'}->{$key} = $val;

您甚至可以使用哈希切片将一堆值插入到一堆键中。

my %filedata = ( Key1 => 123, Key2 => 456 );
@{ $tempHash->{Person}{Home}{Laptop} }{keys %filedata} = values %filedata;

这只是更通用但乏味代码的专用版本

my @keys   = qw(Key1 Key2);
my @values = (123, 456);
@{ $tempHash->{Person}{Home}{Laptop} }{@keys} = @values;