【问题标题】:Retrieving original JSON code from a decoded array node in Perl从 Perl 中的解码数组节点检索原始 JSON 代码
【发布时间】:2012-09-19 20:26:29
【问题描述】:

我正在编写一个脚本,该脚本接收类似于此的对象数组的 JSON 代码:

{
  "array":[
    { "id": 1, "text": "Some text" },
    { "id": 2, "text": "Some text" }
  ]
}

我使用 JSON::XS 对其进行解码,然后过滤掉一些结果。在此之后,我需要将 每个单独节点的 JSON 代码 存储到队列中以供以后处理。这个队列需要的格式也是 JSON,所以我需要为每个节点插入的代码是这样的:

{ "id": 1, "text": "Some text" }

但是,在 decode_json 解码了一个节点之后,剩下的就是每个节点的哈希引用:

print $json->{'array'}[0]; # Would print something like HASH(0x7ffa80c83270)

我知道我可以在散列引用上使用 encode_json 获得类似于原始 JSON 代码的内容,但生成的代码与原始代码不同,UTF-8 字符变得很奇怪,而且似乎有很多额外的处理,特别是考虑到这个脚本必须处理的数据量。

有没有办法从解码的数组节点中检索原始 JSON 代码? JSON::XS 是否将原始块在解码后保留在某个地方?


编辑

关于奇怪的 UTF-8 字符,它们在屏幕上看起来很奇怪:

#!/usr/bin/perl

use utf8;
use JSON::XS;
binmode STDOUT, ":utf8";

$old_json = '{ "text": "Drag\u00f3n" }';
$json = decode_json($old_json);
print $json->{'text'}; # Dragón

$new_json = encode_json($json);
print $new_json; # {"text":"Dragón"}

$json = decode_json($new_json);
print $json->{'text'}; # Dragón

【问题讨论】:

  • 重新编辑:是的,当您使用 UTF-8 对某些内容进行两次编码时,在 UTF-8 终端上看起来会很奇怪。不要那样做。
  • 记住 decode_jsonencode_json 的缩写。

标签: json perl utf-8


【解决方案1】:

encode_json 将生成与使用decode_json 解码之前的原始 JSON 等效的 JSON。使用 UTF-8 编码的字符并不奇怪。

$ cat a.pl
use Encode   qw( encode_utf8 );
use JSON::XS qw( decode_json encode_json );

my $json = encode_utf8(qq!{"name":"\x{C9}ric" }!);
print($json, "\n");
print(encode_json(decode_json($json)), "\n");

$ perl a.pl | od -c
0000000   {   "   n   a   m   e   "   :   " 303 211   r   i   c   "    
0000020   }  \n   {   "   n   a   m   e   "   :   " 303 211   r   i   c
0000040   "   }  \n
0000043

如果您想要一个保留原始 JSON 的解析器,您肯定必须自己编写;现有的不这样做。

【讨论】:

  • 如果你的意思很奇怪,它将 6 个字符 \u2660 的 UTF-8 编码 (5C 75 32 36 36 30) 替换为字符的 UTF-8 编码 (E2 99 A0)代表(♠),你错了。没关系。
  • 所以...现在 JSON 代码进入 MySQL 队列,我将其提取出来,当我尝试对其进行解码时出现此错误:JSON 字符串中的 UTF-8 字符格式错误...有什么想法吗?
  • 是的,cmets 不是问新问题的地方。请务必准确了解您的数据 (use Data::Dumper; local $Data::Dumper::Useqq = 1; print(Dumper(...));)
  • 很抱歉...只是了解规则。我在解码 JSON $json = decode_json(encode_utf8($text)); 之前通过编码为 UTF-8 解决了这个问题
  • 很确定你有两个错误的情况。您正在解码-编码-解码,而不仅仅是解码。
【解决方案2】:

不,这是不可能的。每个 JSON 对象都可以有多个但等效的表示:

{ "key": "abc" }

{
  "key" : "abc" 
}

几乎一样。

因此,只需使用您的模块为您提供的重新编码的 JSON。

  1. 即使 JSON::XS 缓存了这些块,提取它们也将违反封装,因此无法保证在升级模块后仍能正常工作。这是糟糕的设计。

  2. 不关心性能。 XS 模块具有卓越的性能,因为它们是用 C 编码的。如果你对性能有偏执,你不会使用 JSON,而是使用一些二进制格式。而且您不会使用 Perl,而是使用 Fortran ;-)

  3. 您应该将等效数据视为等效数据。即使演示文稿不同。

  4. 如果 unicode 字符看起来很奇怪,但处理正常,则没有问题。如果它们没有得到正确处理,您可能必须指定准确的编码。

【讨论】:

  • 对之前解码的内容重新编码感觉像是一个性能问题......但是,除非我编写自己的解析器,否则我似乎不得不放弃它。非常感谢。
【解决方案3】:

不,它在任何地方都不存在。 “原始 JSON”不是按元素存储的;单次解码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-04
    • 2014-01-19
    • 1970-01-01
    • 1970-01-01
    • 2010-11-24
    • 1970-01-01
    相关资源
    最近更新 更多