使用 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;
我尝试将 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;