自从在Perl中从JSON1升级到JSON2后,混乱的变音符号

时间:2013-05-17 15:47:02

标签: json perl

我想知道为什么有些德国变形金刚在我们的网页上乱成一团。 然后我发现最新版本的JSON(我使用2.07)确实以不同于JSON 1.5的方式转换字符串。

这里的问题是我有一个像

这样的字符串的哈希
use Data::Dumper;
my $test = {
  'fields' => 'überrascht'
};

print Dumper(to_json($test));给了我

$VAR1 = "{ \"fields\" : \"\x{fc}berrascht\" } "; 

使用旧模块

$json = JSON->new();
print Dumper ($json->to_json($test));

给我(正确的结果)

$VAR1 = '{"fields":[{"title":"überrascht"}]}'; 

因此,使用新的JSON 2模块可以破坏变音符号。

我需要什么才能使它们正确?

更新:使用Data :: Dumper显示输出可能不好,因为Dumper使用自己的编码。好吧,Dumper的结果差异表明在这里对待任何事情都是不同的。如布拉德提到的那样描述后端可能更好: 使用Template-Toolkit打印json字符串,然后将其分配给javascript变量以供进一步使用。正确的javascript显示类似这样的内容

{
    "title" : "Geändert",
},

使用我得到的新模块

{
    "title" : "Geändert",
},

目标页面位于8859-1(latin1)。 有什么建议吗?

4 个答案:

答案 0 :(得分:5)

\x{fc}ü,至少在Latin-1,Latin-9等等。此外,ü是Unicode中的代码点U+00FC。但是,我们想要UTF-8(我想)。获取UTF-8字符串文字的最简单方法是使用此编码保存Perl源代码,并将use utf8;放在脚本的顶部。

然后,将字符串编码为JSON会产生正确的输出:

use strict; use warnings; use utf8;
use Data::Dumper; use JSON;
print Dumper encode_json {fields => "nicht überrascht"};

encode_json假设为UTF-8。请阅读documentation了解详情。

输出:

$VAR1 = '{"fields":"nicht überrascht"}';

(JSON模块版本:2.53)

答案 1 :(得分:5)

my $json_text = to_json($data);

的缩写
my $json_text = JSON->new->encode($data);

返回一串Unicode代码点。 U + 00FC确实是“ü”的正确Unicode代码点,因此输出是正确的。 (作为证明,HTML源代码实际上是"ü"。)

很难说出原始输出实际包含的内容(因为您显示的是非ASCII字符),因此很难确定您的问题实际上是什么。

但是在输出字符串之前必须做的一件事是将它从一串代码点转换为字节,比如使用Encodeencodeencode_utf8。 / p>

my $json_cp1252 = encode('cp1252', to_json($data));

my $json_utf8 = encode_utf8(to_json($data));

如果适当的编码是UTF-8,您还可以使用以下任何一种:

my $json_utf8 = to_json($data, { utf8 => 1 });

my $json_utf8 = encode_json($data);

my $json_utf8 = JSON->new->utf8->encode($data);

答案 2 :(得分:2)

请改用encode_json。根据手册,它将给定的Perl数据结构转换为UTF-8编码的二进制字符串。

关于您的更新:如果您确实想在Latin1(ISO-8859-1)中生成JSON,可以尝试:

to_json($test, { latin1 => 1 })

或者

JSON->new->latin1->encode($test)

请注意,如果您转储结果,那么在这种情况下获取\x{fc}的{​​{1}}是正确的。我想问题的根源在于你从某个地方接收Perl的UTF-8格式的文本。在这种情况下,需要JSON模块的ü选项。

您也可以尝试使用latin1代替ascii作为最安全的选项。

另一种解决方案可能是为Template-Toolkit指定输出编码。我不知道这是否可能。或者,您可以在将结果发送到客户端之前将结果编码为最终步骤中的Latin1。

答案 3 :(得分:2)

严格地说,Latin-1编码的JSON是无效的JSON。 JSON spec允许使用UTF-8,UTF-16或UTF-32编码。

如果您希望符合标准,或者您希望确保您的JSON与当前页面和未来基于UTF-8的页面兼容,则需要使用JSON->new->utf8->encode($str)。严格遵守生成的有效JSON可以在将来为您节省许多麻烦。

如果需要,可以使用this trick将UTF-8 JSON转换为使用客户端Javascript的Latin-1。

ascii选项还通过使用有效的JSON unicode转义转义任何非ASCII字符来生成有效的JSON。但是latin1选项没有,因此应该避免恕我直言。除非您在将数据写入客户端时指定编码,否则应该避免utf8(0)选项:utf8(0)utf8选项略有不同,因为它生成Perl字符串而不是字节字符串。如果您使用字符串执行任何I / O而未指定编码,Perl会将其即时转换回Latin-1。 utf8选项生成原始UTF-8字节,非常适合执行原始I / O.