由于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)中。
有人可以向我解释原因吗?
答案 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模块),它读取标量的基础字符串缓冲区,并错误地将其视为字符串的内容。该模块中存在一个错误。