【问题标题】:Parsing Unicode text with TJSONObject returns '????'使用 TJSONObject 解析 Unicode 文本会返回 '????'
【发布时间】:2016-02-12 09:49:20
【问题描述】:

我尝试使用带有 Unicode 字符的 TJSONObject 类,但解析后,我得到 ???? 而不是原始文本。

简单的问题是:

UnicodeString doc = L"{\"alias\":\"Test ЮРИСЛАВ\"}";
ShowMessage(doc);
TJSONObject* jo=new TJSONObject();
jo->Parse(BytesOf(doc), 0);
ShowMessage(jo->ToString());

第一个ShowMessage 正确显示文本:ЮРИСЛАВ
但在解析第二个ShowMessage 后显示???? 而不是ЮРИСЛАВ

我做错了什么?

【问题讨论】:

  • 尝试将String insted of UnicodeString 用于doc 变量或使用UTF8Encode() 函数
  • 我做到了,但结果相同

标签: json delphi c++builder


【解决方案1】:

您正在使用BytesOf(),它使用操作系统默认的 Ansi 编码将UnicodeString 转换为字节数组。 TJSONObject::Parse() 更喜欢 UTF-8。它寻找一个 UTF-8 BOM,如果没有找到,那么它不对字节的编码做任何假设,它只是将它们视为 8 位字符。这在处理非 ASCII 字符时不起作用,您需要改用 UTF-8。要将 UnicodeString 转换为 UTF-8 编码的字节数组,您可以使用 TEncoding::UTF8::GetBytes(),但您必须手动在数组前面添加 UTF-8 BOM:

UnicodeString doc = L"{\"alias\":\"Test ЮРИСЛАВ\"}";
ShowMessage(doc);

TBytes bytes;
bytes.Length = 3 + TEncoding::UTF8::GetByteCount(doc);
bytes[0] = 0xEF;
bytes[1] = 0xBB;
bytes[2] = 0xBF;
TEncoding::UTF8::GetBytes(doc, 1, doc.Length(), bytes, 3);

TJSONObject* jo = new TJSONObject();
jo->Parse(bytes, 0);
ShowMessage(jo->ToString());
//...
delete jo;

话虽如此,您应该直接使用静态TJSONObject::ParseJSONValue() 方法而不是TJSONValue::Parse()ParseJSONValue() 甚至有一个重载,它接受 UnicodeString 作为输入,并将在内部为您将其转换为 UTF-8 编码的字节数组:

UnicodeString doc = L"{\"alias\":\"Test ЮРИСЛАВ\"}";
ShowMessage(doc);
TJSONObject* jo = (TJSONObject*) TJSONObject::ParseJSONValue(doc);
ShowMessage(jo->ToString());
//...
delete jo;

但是,如果您确实需要传入自己的字节数组,ParseJSONValue() 的其他重载允许您指定字节数组是否为 UTF-8 编码(默认情况下假定为 UTF-8),因此您不需要 BOM:

UnicodeString doc = L"{\"alias\":\"Test ЮРИСЛАВ\"}";
ShowMessage(doc);
TJSONObject* jo = (TJSONObject*) TJSONObject::ParseJSONValue(TEncoding::UTF8::GetBytes(doc), 0, true);
ShowMessage(jo->ToString());
//...
delete jo;

【讨论】:

    【解决方案2】:

    改成这样:

    jo = (TJSONObject*) TJSONObject::ParseJSONValue(TEncoding::UTF8::GetBytes(doc), 0);
    

    您应该在解析之前将您的 Unicode 文本转换为 UTF8。

    【讨论】:

    • 可以将doc字符串直接传递给ParseJSONValue(),不需要先转换成UTF-8字节数组。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-22
    • 2020-06-13
    • 2015-01-18
    • 1970-01-01
    相关资源
    最近更新 更多