我对 TIdHttpServer 的 POST 请求包含奇怪的字符,json 字符串

My POST request on TIdHttpServer contains strange characters, json string

我收到 POST 请求时收到的 JSON 字符串有问题。目前这是我阅读它的方式:

procedure TForm1.IdHTTPServer1CommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
  Stream : TStream;
  S : string;
begin
  If ARequestInfo.Command = 'POST' then
  begin
    Stream := ARequestInfo.PostStream;
    if assigned(Stream) then
    begin
      Stream.Position := 0;
      S := UTF8ToAnsi(ReadStringFromStream(Stream));
    end;
  end;
end;

我单独尝试 ReadStringFromStream() 并与 UTF8ToAnsi()AnsiToUTF8() 一起尝试,但我总是得到一个如下所示的字符串:

'['#$A#9'{'#$A#9#9'"test":"bb",'#$A#9#9'"test":"aa"'#$A#9'}'#$A']'

我知道它与编码有关,但我不知道如何解决它。

您知道井号 (#) 表示字符值,而美元 ($) 符号表示十六进制值,对吧。因此 #$A 表示字符十进制 10,恰好表示 NewLine#9 表示字符 9,即 TAB 字符。 return 字符串中没有任何意外。如果你把它输入到理解 NewLine 而没有前面的 CarriageReturn 的东西,它可能看起来像你预期的那样。

例如,调试器对无法以其他方式直观表示的字符使用 # 语法。

您在示例中显示的数据非常好,正如 Tom B 所解释的那样。您正在调试器中查看字符串数据,其中 #A 是换行符,#9 是制表符,所以实际的字符串如下所示:

[
    {
        "test":"bb",
        "test":"aa"
    }
]

哪个有效JSON。

但是,您读取数据的方式不对,尤其是当您使用 Delphi (2009+) 的 Unicode 版本时。您没有将任何值传递给 ReadStringFromString()AByteEncoding 参数,因此它将使用 Indy 的默认编码解码流字节,默认情况下为 7 位 US-ASCII(请参阅 GIdDefaultTextEncoding 变量在 IdGlobal 单元中)。 JSON 默认使用 UTF-8,因此如果 JSON 包含任何非 ASCII 字符,您将损坏它。事后使用 UTF8ToAnsi() 无法解决这个问题。

您的代码应该如下所示:

procedure TForm1.IdHTTPServer1CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
  Stream : TStream;
  S : string;
begin
  If ARequestInfo.CommandType = hcPOST then
  begin
    Stream := ARequestInfo.PostStream;
    if Assigned(Stream) then
    begin
      S := ReadStringFromStream(Stream, -1, IndyTextEncoding_UTF8);
    end
  end
end;

这告诉 Indy 将流字节解码为 UTF-8 到 UTF-16,然后 return 解码字符串(如果您使用 Delphi 的非 Unicode 版本,UTF -16 数据将在退出时转换为 ANSI,受限于 ReadStringFromStream() 的可选 ADestEncoding 参数)。