gpt4 book ai didi

perl decode and encode json preserving order(perl解码和编码json保留顺序)

转载 作者:bug小助手 更新时间:2023-10-22 16:38:53 31 4
gpt4 key购买 nike



I have in a text database field a json encoded chart configuration in the form of:

我在文本数据库字段中有一个json编码的图表配置,其形式为:



{"Name":[[1,1],[1,2],[2,1]],"Name2":[[3,2]]}


The first number of these IDs is a primary key of another table. I'd like to remove those entries with a trigger when the row is deleted, a plperl function would be good except it does not preserve the order of the hash and the order is important in this project. What can I do (without changing the format of the json encoded config)? Note: the chart name can contain any characters so it's hard to do it with regex.

这些ID中的第一个数字是另一个表的主键。我想在删除行时用触发器删除这些条目,plperl函数会很好,除非它不保留哈希的顺序,并且顺序在这个项目中很重要。我能做什么(不改变json编码配置的格式)?注意:图表名称可以包含任何字符,因此很难使用regex。


更多回答

JSON.org: "An object is an unordered set of name/value pairs." If you want to preserve order, use an array instead of an object. Then, just grep to keep all but the item you want to remove.

JSON.org:“对象是一组无序的名称/值对。”如果你想保持顺序,可以使用数组而不是对象。然后,只需grep即可保留除要删除的项之外的所有项。

Every perl JSON parser I've looked at represents JSON objects as hash tables, which, of course, don't preserve order. It's not something you can really rely on with JSON objects in general as already mentioned. Maybe use an array if order matters?

我看过的每一个perl JSON解析器都将JSON对象表示为哈希表,当然,这并不能保持顺序。正如前面提到的那样,JSON对象通常不能真正依赖它。如果顺序很重要,也许可以使用数组?

The problem is that the website is written in PHP which preserves the order so that is how the order of the charts are saved. I'm not aware that there would be a plphp for postgres so I guess I could do a system() call from a plperl function but that would be a horribe solution.

问题是,网站是用PHP编写的,它保留了顺序,所以图表的顺序就是这样保存的。我不知道postgres会有一个plphp,所以我想我可以从plperl函数中调用system(),但这将是一个可怕的解决方案。

I looked into JSON::PP code and I'd just need to add a tie to IxHash at the beginning of the function called object(). I can't believe no one ever needed that! Having to modify OS povided files introduces more problems than it solves so I'll just modify my json in PHP right after deletion and hope no one will delete more data anywhere else or calls my cleanup function. How wondeful. Or should I go with the plperl system() call from the trigger? I'm between a rock and a hard place.

我研究了JSON::PP代码,只需要在名为object()的函数的开头添加一个IxHash绑定。我不敢相信从来没有人需要它!必须修改操作系统提供的文件会带来比解决更多的问题,所以我只会在删除后立即在PHP中修改json,希望没有人会在其他地方删除更多数据或调用我的清理函数。真是糟透了。或者我应该从触发器调用plperlsystem()吗?我处于进退两难的境地。

优秀答案推荐

You need to use a streaming JSON decoder, such as JSON::Streaming::Reader. You could then store your JSON as an array of key/value pairs, instead of a hash.

您需要使用流式JSON解码器,例如JSON::streaming::Reader。然后,您可以将JSON存储为键/值对的数组,而不是散列。



The actual implementation of how you might use do this is highly dependent on the structure of your data, but given the simple example provided... here's a simple implementation.

如何使用的实际实现在很大程度上取决于数据的结构,但给定所提供的简单示例。。。这里有一个简单的实现。



use strict;
use warnings;
use JSON::Streaming::Reader;
use JSON 'to_json';

my $s = '{"Name":[[1,1],[1,2],[2,1]],"Name2":[[3,2]]}';

my $jsonr = JSON::Streaming::Reader->for_string($s);

my @data;
while (my $token = $jsonr->get_token) {
my ($key, $value) = @$token;
if ($key eq 'start_property') {
push @data, { $value => $jsonr->slurp };
}
}

print to_json(\@data);


The output for this script is always: -

此脚本的输出始终为:-



[{"Name":[[1,1],[1,2],[2,1]]},{"Name2":[[3,2]]}]


Well, I managed to solve my problem, but it's not a general solution so it will probably not help the casual reader. Anyway I got the order of keys using the help of the database, I called my function like this:

好吧,我设法解决了我的问题,但这不是一个通用的解决方案,所以它可能对普通读者没有帮助。无论如何,我使用数据库的帮助获得了密钥的顺序,我这样调用我的函数:



SELECT remove_from_chart(
chart_config,
array(select * from json_object_keys(chart_config::json)),
id);


then I walked through the keys in the order of the second parameter and put the results in a new tied (IxHash) hash and json encoded it.

然后,我按照第二个参数的顺序遍历键,并将结果放入一个新的绑定(IxHash)哈希中,并对其进行json编码。



It's pretty sad that there is no perl json decoder that could preserve the key order when everything else I work with, at least on this project, does it (php, postgres, firefox, chrome).

令人遗憾的是,当我使用的其他所有东西(至少在这个项目中)都这样做时,没有perl-json解码器可以保留密钥顺序(php、postgres、firefox、chrome)。



@soger, thanks for the idea in your comment above from 5 years ago!

@索格,谢谢你5年前在上面的评论中的想法!



I looked into JSON::PP code and I'd just need to add a tie to IxHash at the beginning of the function called object().



Brilliant solution! Thanks for the idea. I figured out how to implement this using the Monkey::Patch module to wrap the JSON::PP::object() function to make it use Tie::IxHash, without touching the installed JSON::PP files:

绝妙的解决方案!谢谢你的想法。我想好了如何使用Monkey::Patch模块来包装JSON::PP::object()函数,使其使用Tie::IxHash来实现这一点,而无需接触安装的JSON::PP文件:


use Monkey::Patch qw[patch_package];

# Monkey-patch JSON::PP::object() subroutine to use Tie::IxHash.
my $handle = patch_package 'JSON::PP' => 'object' => sub {
my $orig = shift;
my %obj;
tie %obj, 'Tie::IxHash' or die "tie(\%obj, 'Tie::IxHash') failed!\n";
$orig->(\%obj)
};

After running the code above, as long as $handle remains in scope, JSON::PP::decode_json will use Tie::IxHash for all JSON objects. I tested by reading in a JSON file, decoding it with JSON::PP::decode_json, then encoded the resulting data structure back into JSON with JSON::PP::encode_json and wrote that to a new JSON file. I then ran the original JSON file and the new JSON file through jq . to normalize the formatting and compared the results. They were 100% byte-for-byte identical. 👍

运行以上代码后,只要$handle仍在作用域中,JSON::PP::decode_JSON将对所有JSON对象使用Tie::IxHash。我通过读取一个JSON文件进行测试,用JSON::PP::decode_JSON对其进行解码,然后用JSON:PP::encode_JSON将生成的数据结构编码回JSON,并将其写入一个新的JSON文件。然后,我通过jq运行原始JSON文件和新的JSON文件。以规范化格式并比较结果。它们完全相同。👍


(Of course, ideally JSON::PP should offer this as a built-in option out of the box!)

(当然,理想情况下JSON::PP应该将其作为开箱即用的内置选项提供!)



JSON objects are unordered. You will have to encode the desired order into your data somehow

JSON对象是无序的。您必须以某种方式将所需的顺序编码到数据中



{"Name":[[1,1],[1,2],[2,1]],"Name2":[[3,2]], "__order__":["Name","Name2"]}

[{"Name":[[1,1],[1,2],[2,1]]},{"Name2":[[3,2]]}]


May be you want streaming decoder of JSON data like SAX parser. If so then see JSON::Streaming::Reader, or JSON::SL.

您可能想要类似SAX解析器的JSON数据流解码器。如果是这样,请参阅JSON::Streaming::Reader或JSON::SL。


更多回答

Thank you, I think I got the gist of what you are doing here, so I accepted your response because it's a lot more general than what I was doing before and I can reformat the data to what I want.

谢谢你,我想我已经了解了你在这里所做的事情的要点,所以我接受了你的回复,因为它比我以前做的要笼统得多,我可以根据我的需要重新格式化数据。

I asked the developer of JSON::PP if he'd add an option to tie to IxHash every hash created during the decode and the answer was "Sorry, no." I wish I understood why this is such a taboo.

我问JSON::PP的开发人员,他是否愿意添加一个选项,将解码过程中创建的每个哈希绑定到IxHash,答案是“对不起,不。”我希望我能理解为什么这是一个禁忌。

Monkey::Patch, I like that! I didn't know about it. I ended up creating a TiedJSON package which messed with the original JSON::PP package's namespace putting new functions like a tied_decode_json() in it and my TiedJSON package has a decode_json() too which calls that.

猴子:帕奇,我喜欢!我不知道。我最终创建了一个TiedJSON包,它破坏了原始JSON::PP包的命名空间,在其中放入了像tied_decode_JSON()这样的新函数,而我的TiedJSON软件包也有一个decode_JSON()来调用它。

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com