使用 TJSONObject returns '????' 解析 Unicode 文本

Parsing Unicode text with TJSONObject returns '????'

我尝试将 TJSONObject 类 与 Unicode 字符一起使用,但在解析后,我得到 ???? 而不是原始文本。

简单的问题是:

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

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

我做错了什么?

改成这样:

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

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

您正在使用 BytesOf(),它使用 OS 默认 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;