从 json utf-8 编码字符串
encode string from json utf-8
我有一个 JSON 文件 {"data":[{"clientName":"Is Такой текст"}]}
是 UTF-8 编码的,我正在尝试使用 ShowMessage()
函数查看标签 clientName
中的文本.
我得到的不是普通文本,而是“Is strangeText”。我知道问题出在编码上,但我不知道如何解决它。
procedure TForm1.jsonTest;
var
JSONData, JSON: TJSONObject;
jArr: TJSONArray;
s: TStringList;
i, j: Integer;
jValue: TJSonValue;
JsonArray: TJSONArray;
jPair: TJSONPair;
begin
json := TJSONObject.Create;
s := TStringList.Create;
try
S.LoadFromFile('clientOrders.json');
text := S.Text;
JSON := TJSONObject.ParseJSONValue(BytesOf(text),0) as TJSONObject;
if JSON <> nil then
begin
jPair := JSON.Get(0);
jArr := jPair.JsonValue as TJSONArray;
for I := 0 to jArr.Size-1 do
begin
JSONData := jArr.Get(I) as TJSONObject;
for j := 0 to JSONData.Size - 1 do
begin
ShowMessage(JSONData.Get(j).JsonValue.ToString);
end;
end;
end
else
raise Exception.Create('This is not a JSON');
finally
json.Free;
s.Free;
jValue.Free;
end;
end;
假设你是运行这段代码Windows,那么问题是two-fold:
你没有告诉 TStringList.LoadFromFile()
文件的编码是什么。因此,除非文件以 UTF-8 BOM 开头(JSON 文件不太可能),否则它将被解码为 ANSI,而不是 UTF-8,从而损坏任何 NON-ASCII 字符。
您在未指定编码的情况下将解码的文本转换回字节。您正在使用的 ParseJSONValue()
的重载需要 UTF-8 编码的字节,但是 BytesOf()
将编码为 ANSI,而不是 UTF-8,从而进一步破坏 non-ASCII 个字符。
这就是为什么您从 JSON.
收到垃圾文本的原因
您的代码也存在其他问题。即,内存泄漏和 double-free,由于您对 initlal TJSONObject
.
的管理不当
试试这个。
procedure TForm1.jsonTest;
var
JSONData, JSON: TJSONObject;
jArr: TJSONArray;
s: TStringList;
i, j: Integer;
jValue: TJSonValue;
data: string;
begin
s := TStringList.Create;
try
s.LoadFromFile('clientOrders.json', TEncoding.UTF8);
data := s.Text;
finally
s.Free;
end;
{ Alternatively:
data := IOUtils.TFile.ReadAllText('clientOrders.json', TEncoding.UTF8);
}
jValue := TJSONObject.ParseJSONValue(TEncoding.UTF8.GetBytes(data), 0);
if jValue = nil then
raise Exception.Create('This is not a JSON');
try
JSON := jValue as TJSONObject;
jArr := JSON.Get(0).JsonValue as TJSONArray;
for I := 0 to jArr.Size-1 do
begin
JSONData := jArr.Get(I) as TJSONObject;
for j := 0 to JSONData.Size - 1 do
begin
ShowMessage(JSONData.Get(j).JsonValue.ToString);
end;
end;
end;
finally
jValue.Free;
end;
end;
或者,不要将文件字节解码为 string
只是为了将它们转换回字节,只需将它们 as-is 加载到 ParseJSONValue()
,例如:
procedure TForm1.jsonTest;
var
...
jValue: TJSonValue;
data: TBytesStream;
begin
data := TBytesStream.Create;
try
data.LoadFromFile('clientOrders.json');
jValue := TJSONObject.ParseJSONValue(data.Bytes, 0);
...
finally
data.Free;
end;
end;
或:
procedure TForm1.jsonTest;
var
...
jValue: TJSonValue;
data: TBytes;
begin
data := IOUtils.TFile.ReadAllBytes('clientOrders.json');
jValue := TJSONObject.ParseJSONValue(data, 0);
...
end;
我有一个 JSON 文件 {"data":[{"clientName":"Is Такой текст"}]}
是 UTF-8 编码的,我正在尝试使用 ShowMessage()
函数查看标签 clientName
中的文本.
我得到的不是普通文本,而是“Is strangeText”。我知道问题出在编码上,但我不知道如何解决它。
procedure TForm1.jsonTest;
var
JSONData, JSON: TJSONObject;
jArr: TJSONArray;
s: TStringList;
i, j: Integer;
jValue: TJSonValue;
JsonArray: TJSONArray;
jPair: TJSONPair;
begin
json := TJSONObject.Create;
s := TStringList.Create;
try
S.LoadFromFile('clientOrders.json');
text := S.Text;
JSON := TJSONObject.ParseJSONValue(BytesOf(text),0) as TJSONObject;
if JSON <> nil then
begin
jPair := JSON.Get(0);
jArr := jPair.JsonValue as TJSONArray;
for I := 0 to jArr.Size-1 do
begin
JSONData := jArr.Get(I) as TJSONObject;
for j := 0 to JSONData.Size - 1 do
begin
ShowMessage(JSONData.Get(j).JsonValue.ToString);
end;
end;
end
else
raise Exception.Create('This is not a JSON');
finally
json.Free;
s.Free;
jValue.Free;
end;
end;
假设你是运行这段代码Windows,那么问题是two-fold:
你没有告诉
TStringList.LoadFromFile()
文件的编码是什么。因此,除非文件以 UTF-8 BOM 开头(JSON 文件不太可能),否则它将被解码为 ANSI,而不是 UTF-8,从而损坏任何 NON-ASCII 字符。您在未指定编码的情况下将解码的文本转换回字节。您正在使用的
ParseJSONValue()
的重载需要 UTF-8 编码的字节,但是BytesOf()
将编码为 ANSI,而不是 UTF-8,从而进一步破坏 non-ASCII 个字符。
这就是为什么您从 JSON.
收到垃圾文本的原因您的代码也存在其他问题。即,内存泄漏和 double-free,由于您对 initlal TJSONObject
.
试试这个。
procedure TForm1.jsonTest;
var
JSONData, JSON: TJSONObject;
jArr: TJSONArray;
s: TStringList;
i, j: Integer;
jValue: TJSonValue;
data: string;
begin
s := TStringList.Create;
try
s.LoadFromFile('clientOrders.json', TEncoding.UTF8);
data := s.Text;
finally
s.Free;
end;
{ Alternatively:
data := IOUtils.TFile.ReadAllText('clientOrders.json', TEncoding.UTF8);
}
jValue := TJSONObject.ParseJSONValue(TEncoding.UTF8.GetBytes(data), 0);
if jValue = nil then
raise Exception.Create('This is not a JSON');
try
JSON := jValue as TJSONObject;
jArr := JSON.Get(0).JsonValue as TJSONArray;
for I := 0 to jArr.Size-1 do
begin
JSONData := jArr.Get(I) as TJSONObject;
for j := 0 to JSONData.Size - 1 do
begin
ShowMessage(JSONData.Get(j).JsonValue.ToString);
end;
end;
end;
finally
jValue.Free;
end;
end;
或者,不要将文件字节解码为 string
只是为了将它们转换回字节,只需将它们 as-is 加载到 ParseJSONValue()
,例如:
procedure TForm1.jsonTest;
var
...
jValue: TJSonValue;
data: TBytesStream;
begin
data := TBytesStream.Create;
try
data.LoadFromFile('clientOrders.json');
jValue := TJSONObject.ParseJSONValue(data.Bytes, 0);
...
finally
data.Free;
end;
end;
或:
procedure TForm1.jsonTest;
var
...
jValue: TJSonValue;
data: TBytes;
begin
data := IOUtils.TFile.ReadAllBytes('clientOrders.json');
jValue := TJSONObject.ParseJSONValue(data, 0);
...
end;