perl 更改JSON文件的键,同时保留括号部分中的数据

hmae6n7t  于 2023-02-19  发布在  Perl
关注(0)|答案(2)|浏览(124)

我的第一个想法是简单地“搜索和替换底层JSON代码,逐行检查它。这将不会起作用,因为相同的“关键字”可以用于不同的地方,但只有一个特定的行需要更改。
然后我想,读入现有的数据,创建一个新条目,将数据推到那个块中,然后删除原来的键。前者可以工作...但是原始的和它的所有数据保持不变。
这是一个简化的版本。(不要认为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行,每个项目可能有几十个广告,几十个项目!!
他们希望将项目1“ad_1”更改为“ad_101”
正如您所看到的,两个项目都有名为“ad_1”的广告,因此简单地搜索和替换底层文本代码文件是行不通的。
如果我使用$project1-〉{“ad_campaign”},我可以获得所有数据。如果我用途:$project1-〉{“ad_campaign”}=$new_ad_id...它将创建一个新部分(我可以一行一行的复制数据)......但是我还是不能去掉原来的“ad_1”项!($project1-〉{“ad_campaign”}-〉{“ad_1”} =null(不允许裸字)/“null”/“”无效-即使尝试先删除内部数据。这可能导致data 1:''、data 2:''等)
我真正需要的是一种方法来执行$customer1-〉{“ad_campaign”}-〉{“new_ad_id”},以便简单地更改第三个键。(我已经在Google上搜索了“change”/“replace”JSON键,但没有结果......特别是当我使用Perl时)
又一个“扳手在工作”;文件被保存为单行,(使用JSON::PP“漂亮”似乎添加了太多空格-制表符缩进似乎更好)所以很难拆分,无论如何都要逐行扫描。(另一个想法是通过文件重复,一旦命中“customer 1”就设置一个标志,另一个循环,另一个标志为“ad_campaign”,然后最后循环寻找“ad_1”。似乎有点低效...加上所有解码的数据都在哈希中!)
请记住,我已经简化了这段代码。在“Project 1”和“ad_campaign”之间,每个项目可以有另外50个键:值对
可能有一些简单的解决方案,通过散列“参数”来查找/更改值......但我还没有找到它!

  • 我在别的地方读到:删除$JSON-〉{“project 1”}-〉{“ad_campaign”}-〉{“ad_id”},但这也没有删除原始内容!
    刚刚想到一个结尾也许我可以做一些类似“indexOf”的操作来定位project 1/ad_campaign等,然后做split/splice,推送一半的数据,然后再拆分一次等,直到我找到要替换的单词。但同样,对于一个非常基本的问题来说,这似乎有点过头了
0dxa2lsx

0dxa2lsx1#

请尝试以下代码。

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_1ad_101密钥引用相同的数据,即

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

[编辑-回答部分评论]
我修改了data的值,突出显示ad_1ad_101中的引用指向JSON文档中的唯一数据,您没有提供任何数据,所以我创建了一些数据。
使用from_jsonto_json而不是decode_jsonencode_json纯粹是为了允许控制pretty参数。使用适合您的用例的变体。查看文档here

n53p2ov0

n53p2ov02#

另一种选择是使用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"]}}}

相关问题