从 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;