更改 JSON 文件的密钥,同时保留该括号部分中的数据

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

我的第一个想法是一个简单的“搜索和替换底层 JSON 代码,逐行检查它。这不会起作用,因为可以在不同的地方使用相同的“关键字”,但只需要更改一个特定的行。

然后我想,把现有的数据读进去,新建一个entry,把数据push到那个block里,然后把原来的key删掉。前者有效……但原件及其所有数据完好无损。

这里是简化版。 (不要认为 500 多行会受到赞赏)

{
project 1:{
     ad_campaign:{
       ad_1{
          data1,
          data2
       },
       ad_2{
         data1,
         data2
       }
     }
}
project 2:{
     ad_campaign:{
     ad_1{
        data1,
        data2
        }
     ad_201{
       data1,
       data2
       }
     }
}
}

“数据”条目是每个广告 6 行,每个项目可能有几十个广告,几十个项目!!

他们想将 Projec1“ad_1”更改为“ad_101”

如您所见,两个项目都有名为“ad_1”的广告,因此无法简单地搜索和替换底层文本代码文件。

如果我使用$project1->{"ad_campaign"},我可以获得所有数据。如果我然后使用: $project1->{"ad_campaign"}=$new_ad_id ...它会创建一个新部分(我 =could= 然后逐行复制数据)...但我仍然无法摆脱原始“ad_1”条目! ($project1->{"ad_campaign"}->{"ad_1"} =null (不允许裸词) / "null" / "" 无效 - 即使在尝试先删除内部数据时也是如此。这可能会导致 data1 :'',data2:'' 等)

我真正需要的是一种方法来执行 $customer1->{"ad_campaign"}->{"new_ad_id"} 来简单地更改第三个键。 (我用谷歌搜索“更改”/“替换”JSON 键,但没有结果......尤其是当我使用 PERL 时)

又一个“工作中的扳手”;该文件被保存为一行,(使用 JSON::PP “漂亮”似乎添加了太多空格 - 制表符缩进似乎更好)因此很难分开,并且无论如何都要逐行扫描。 (另一个想法是通过文件重复,设置一个标志一旦命中“customer1”,另一个循环,另一个标志“ad_campaign”,然后最后循环寻找“ad_1”。似乎有点低效......加上所有解码数据无论如何都在哈希中!)

请记住,我已经简化了这段代码。在“Project1”和“ad_campaign”之间可以是另外 50 个键值对每个项目

可能有一些简单的解决方案通过散列“参数”查找/更改值......但我还没有找到它!

  • 我在其他地方读到:删除 $JSON->{"project1"}->{"ad_campaign"}->{"ad_id"} 但这也没有删除原件!

只是有一个结束的想法:也许我可以做类似“indexOf”的事情来定位 project1/ad_campaign 等,然后进行拆分/拼接,推送一半数据,然后再次拆分等,直到我找到要替换的词。但同样,对于一个非常基本的问题来说,这似乎有点过分了

json perl hash
2个回答
2
投票

尝试下面的代码。


use strict ;
use warnings;
use feature 'say';

use JSON;

my $data = <<EOM;
{
    "project 1": {
      "ad_campaign": {
        "ad_1": [
          "p1: ad:1 data1",
          "p1: ad:1 data2"
        ],
        "ad_2": [
          "p1: ad:2 data1",
          "p2: ad:2 data2"
        ]
      }
    },
    "project 2": {
      "ad_campaign": {
        "ad_1": [
          "p2: ad:1 data1",
          "p2: ad:1 data2"
        ],
        "ad_201": [
          "p2: ad:201 data1",
          "p2: ad:201 data2"
        ]
      }
    }
  }
EOM

my $in = from_json($data);

# create "ad_101" to reference to the existing "ad_1" data tree
$in->{"project 1"}{"ad_campaign"}{"ad_101"} = $in->{"project 1"}{"ad_campaign"}{"ad_1"};

# now delete the reference to "ad_1"
delete $in->{"project 1"}{"ad_campaign"}{"ad_1"};


# using pretty & canonical here to make the results easier to read
# don't use pretty if you want all JSON output as a single line
say to_json($in, {pretty => 1, canonical => 1});

输出是

{
   "project 1" : {
      "ad_campaign" : {
         "ad_101" : [
            "p1: ad:1 data1",
            "p1: ad:1 data2"
         ],
         "ad_2" : [
            "p1: ad:2 data1",
            "p2: ad:2 data2"
         ]
      }
   },
   "project 2" : {
      "ad_campaign" : {
         "ad_1" : [
            "p2: ad:1 data1",
            "p2: ad:1 data2"
         ],
         "ad_201" : [
            "p2: ad:201 data1",
            "p2: ad:201 data2"
         ]
      }
   }
}

要注意的关键点是 perl 中的嵌套哈希使用引用,这类似于 C/C++ 领域中的指针。意味着在运行这条线后

$in->{"project 1"}{"ad_campaign"}{"ad_101"} = $in->{"project 1"}{"ad_campaign"}{"ad_1"};

ad_1
ad_101
键引用相同的数据,即

[
   "p1: ad:1 data1",
   "p1: ad:1 data2"
],

[编辑 - 回答一些评论]

我更改了

data
值以突出显示
ad_1
ad_101
中的引用指向 JSON 文档中的唯一数据。你没有提供任何数据,所以我做了一些。

使用

from_json
to_json
而不是
decode_json
encode_json
纯粹是为了允许控制
pretty
参数。使用适合您的用例的变体。在此处查看文档


1
投票
另一个选择是使用

jq,而不是 Perl

假设

data.json

包含这个

{ "project 1": { "ad_campaign": { "ad_1": [ "p1: ad:1 data1", "p1: ad:1 data2" ], "ad_2": [ "p1: ad:2 data1", "p2: ad:2 data2" ] } }, "project 2": { "ad_campaign": { "ad_1": [ "p2: ad:1 data1", "p2: ad:1 data2" ], "ad_201": [ "p2: ad:201 data1", "p2: ad:201 data2" ] } } }
这个单线做重命名

$ jq '."project 1".ad_campaign |= ( .ad_101 = .ad_1 | del(.ad_1) ) ' data.json
输出是

{ "project 1": { "ad_campaign": { "ad_2": [ "p1: ad:2 data1", "p2: ad:2 data2" ], "ad_101": [ "p1: ad:1 data1", "p1: ad:1 data2" ] } }, "project 2": { "ad_campaign": { "ad_1": [ "p2: ad:1 data1", "p2: ad:1 data2" ], "ad_201": [ "p2: ad:201 data1", "p2: ad:201 data2" ] } } }
要使 

jq

 输出为单行,请将 
-c
 选项添加到命令行

$ jq -c '."project 1".ad_campaign |= ( .ad_101 = .ad_1 | del(.ad_1) ) ' data.json {"project 1":{"ad_campaign":{"ad_2":["p1: ad:2 data1","p2: ad:2 data2"],"ad_101":["p1: ad:1 data1","p1: ad:1 data2"]}},"project 2":{"ad_campaign":{"ad_1":["p2: ad:1 data1","p2: ad:1 data2"],"ad_201":["p2: ad:201 data1","p2: ad:201 data2"]}}}
    
© www.soinside.com 2019 - 2024. All rights reserved.