我的第一个想法是一个简单的“搜索和替换底层 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 个键值对每个项目
可能有一些简单的解决方案通过散列“参数”查找/更改值......但我还没有找到它!
只是有一个结束的想法:也许我可以做类似“indexOf”的事情来定位 project1/ad_campaign 等,然后进行拆分/拼接,推送一半数据,然后再次拆分等,直到我找到要替换的词。但同样,对于一个非常基本的问题来说,这似乎有点过分了
尝试下面的代码。
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
参数。使用适合您的用例的变体。在此处查看文档
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"]}}}