Perl:为什么我需要自JSON 2.xx后明确设置latin1标志?

时间:2013-06-05 11:53:08

标签: json perl

由于JSON 2.xx我需要设置latin1标志才能使变音符号对于html文档安全:

my $obj_with_umlauts = {
    title  => 'geändert',
}


my $json = JSON->new()->latin1(1)->encode($obj_with_umlauts);

这不是必须使用JSON 1.xx:

my $json = JSON->new()->objToJson($obj_with_umlauts);

html文档位于iso-8559-1(meta-tag)中。

有人可以向我解释原因吗?

2 个答案:

答案 0 :(得分:6)

这是一个巨大的虫子,你在这里开放。

我怀疑答案是“在JSON.pm的字符处理中修复了一个错误”。但是如果没有关于你的情况的更多信息,很难知道发生了什么。

如何设置$string_with_umlauts?您如何编码写入HTML文档的数据?

您是否想要正确处理utf8数据(您真的应该)或者您是否认为自己生活在Latin1世界中?

重要的是要意识到,如果您完全忽略Unicode注意事项,那么通常看起来您的程序正常工作,因为错误经常会相互抵消。当您开始解决Unicode问题时,看起来您的程序会变得更糟,直到您解决所有问题。

Perl Unicode Tutorial是开始了解这些事情的好地方。

P.S。它是“Perl”,而不是“PERL”。

答案 1 :(得分:4)

你在说什么?

$ perl -MJSON -E'
   say $JSON::VERSION;
   my $json = JSON->new()->objToJson(["\xE4"]);
   say sprintf "%v02X", $json;
'
1.15
5B.22.E4.22.5D         # Unicode code points for ["ä"]

$ perl -MJSON -E'
   say $JSON::VERSION;
   my $json = JSON->new()->encode(["\xE4"]);
   say sprintf "%v02X", $json;
'
2.59
5B.22.E4.22.5D         # Unicode code points for ["ä"]

这两个字符串是相同的!事实上,添加->latin1()并没有改变任何东西,因为Unicode代码点U + 00E4的iso-8859-1编码是E4。

$ perl -MJSON -E'
   say $JSON::VERSION;
   my $json = JSON->new()->latin1()->encode(["\xE4"]);
   say sprintf "%v02X", $json;
'
2.59
5B.22.E4.22.5D         # iso-8859-1 encoding of ["ä"]

最后两个之间有一个区别:它在标量中的存储方式不同。这应该完全没有区别。如果代码对它们的处理方式不同,那么该代码会错误地读取标量中的数据,并且 代码是错误的。


  

$ string_with_umlauts definetly是winLatin中的一个字符串

那是第一个错误。

JSON需要解码文本字符串(Unicode代码点的字符串),而不是编码文本。

也就是说,使用iso-8859-1编码的字符串和一串Unicode代码点之间没有区别。例如,当使用iso-8859-1编码时,“ä”是字节E4,它是Unicode代码点U + 00E4,两个不同的表示法用于相同的数字。

如果字符串是使用cp1252编码的,那么你就会遇到字符问题,ƒ“......†‡‡<ŒŽ''”“• - 〜™š>œžŸ(cp1252中的字符但是不在iso-8859-1)。例如,当使用cp1252编码时,“€”是字节80,但它是Unicode代码点U + 20AC。 0x80!= 0x20AC。

  

html文档位于iso-8559-1(meta-tag)中。

然后在某些时候,你必须将输出编码为iso-8859-1。您可以使用:encoding图层,或使用Encode的encode或使用JSON的->latin1指令来执行此操作。使用这个最终选项的好处是它会导致JSON在尝试编码之前转义iso-8859-1字符集之​​外的任何字符。

  

有人可以向我解释原因吗?

您有一个代码(一个XS模块),它读取标量的基础字符串缓冲区,并错误地将其视为字符串的内容。该模块中存在一个错误。