【问题标题】:JSON returned by TIdHTTP cannot be decodedTIdHTTP 返回的 JSON 无法解码
【发布时间】:2018-03-20 00:26:23
【问题描述】:

我有以下代码:

    var
      MemoryStream1: TMemoryStream;
      IdHTTP1: TIdHTTP;
      Bytes1: TBytes;
      s1: string;
    begin             
      IdHTTP1 := TIdHTTP.Create(nil);
      MemoryStream1 := TMemoryStream.Create;
      IdHTTP1.Get('https://restcountries.eu/rest/v2/all', MemoryStream1);
      MemoryStream1.Position := 0;
      MemoryStream1.SaveToFile('C:\Temp\MemoryStream1.txt');
      MemoryStream1.Position := 0;
      SetLength(Bytes1, MemoryStream1.Size);
      MemoryStream1.Read(Bytes1[0], MemoryStream1.Size);
      s1 := TEncoding.UTF8.GetString(Bytes1);

在最后一行失败并显示消息“目标多字节代码页中的 unicode 字符不存在映射”

但是,我可以在 HttpAnalyzer 中清楚地看到返回的 JSON。

文件“C:\Temp\MemoryStream1.txt”以十六进制“1F8B0800000000000003DC9BED6F1BB7”开头,而我期待与 { - 左大括号 - 作为第一个字符相对应的内容

当我尝试 s1 := TEncoding.Unicode.GetString(Bytes1);

字符串 s1 包含“中文”字符。

【问题讨论】:

  • 只需调用s1 := IdHTTP1.Get('https://restcountries.eu/rest/v2/all');,重载返回对字符串的响应,让Indy为你完成解码工作。
  • 谢谢维多利亚。这当然是一种简化。但是,我在 s1 中得到了相同的字符,我需要找到一种方法将其转换为我可以处理的 JSON 字符串。
  • 在网络浏览器中调用它会发生什么?还是 Postman 之类的 REST 调试工具?我敢打赌,问题出在服务器的响应上。
  • 很高兴你发现了你的问题。但是您不应该将答案编辑到您的问题中。应该鼓励您在下面将其作为实际答案发布。
  • PS - 顺便说一句,如果您要下载到TMemoryStream,然后立即将其保存到文件中,那么您应该改用TFileStream。这对于非常大的文件尤其重要——您肯定不想将其下载到内存中,然后转身将其转储到文件中。当然,您首先希望它直接进入文件。

标签: json delphi idhttp


【解决方案1】:

我解决了。显然,gzip 没有解压缩。必须自己做。如下:

    var
      IdHTTP1: TIdHTTP;
      a1: AnsiString;
      s1: string;
      MemoryStream1, MemoryStream2: TMemoryStream;
    begin             
      Screen.Cursor := crHourGlass;
      IdHTTP1 := TIdHTTP.Create(nil);
      MemoryStream1 := TMemoryStream.Create;
      MemoryStream2 := TMemoryStream.Create;
      IdHTTP1.Get('https://restcountries.eu/rest/v2/all', MemoryStream1);
      MemoryStream1.Position := 0;
      IdCompressorZLib1.DecompressGZipStream(MemoryStream1, MemoryStream2);
      FreeAndNil(MemoryStream1);
      MemoryStream2.Position := 0;
      SetLength(a1, MemoryStream2.Size);
      MemoryStream2.Read(a1[1], MemoryStream2.Size);   
     //  AnsiString a1 now contains the decompressed data

【讨论】:

  • 您的原始代码一开始就没有向服务器请求压缩,因此服务器根本不应该发送压缩响应。如果是这样,那就是需要向网站管理员报告的服务器端错误。但即便如此,如果响应被压缩,您也不需要手动解压缩它。将TIdCompressorZLib 对象分配给TIdHTTP.Compressor 属性,让TIdHTTP 为您处理解压。
  • 我无法重现该问题。使用带有 Delphi XE2 的最新版本的 Indy 10,响应不是 gzip 压缩的,并且您问题中显示的原始代码可以按原样正常工作,无需更改。
  • 我有 XE8。也许这就是它表现不同的原因
  • Delphi 版本无关紧要。其他事情正在发生。除非客户端要求,否则服务器不应压缩响应。因此,要么您的 TIdHTTP 在不应该发送 Accept-Encoding: gzip 请求标头时错误地发送(默认情况下,如果没有分配 Compressor,它不会这样做,除非您手动设置 TIdHTTP.Request.AcceptEncoding 属性),或者您显示的代码不是您的真实代码。
  • 我认为你是正确的雷米。感谢您指出这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-12
  • 1970-01-01
  • 1970-01-01
  • 2016-09-26
相关资源
最近更新 更多