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

问题描述 投票:3回答:2

我收到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()and AnsiToUTF8(),但我一直看到这样的字符串:

'[' #$ A#9 '{' #$ A#9#9 ' “测试”: “BB”,' #$ A#9#9 ' “测试”: “AA”' #$ A#9' } '#$ A']”

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

json rest delphi post delphi-10.1-berlin
2个回答
4
投票

你知道哈希(#)符号表示一个字符值,而美元($)符号表示十六进制值,是吗?因此,#$A表示字符十进制10,恰好表示NewLine#9表示字符9,这是TAB字符。返回字符串中没有任何意外。如果你把它喂成一个理解NewLine而没有前面的CarriageReturn的东西,它可能看起来像你预期的那样。

例如,调试器使用#-syntax表示无法以其他方式表示的字符。


2
投票

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

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

哪个是有效的JSON。

但是,您阅读数据的方式并不正确,尤其是如果您使用的是Unicode版本的Delphi(2009+)。您没有将任何值传递给AByteEncodingReadStringFromString()参数,因此它将使用Indy的默认编码对流字节进行解码,默认情况下为7位US-ASCII(请参阅GIdDefaultTextEncoding单元中的IdGlobal变量)。 JSON默认使用UTF-8,因此如果JSON包含任何非ASCII字符,则会损坏JSON。在事实之后使用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,然后返回解码后的字符串(如果您使用的是非Unicode版本的Delphi,UTF-16数据将在退出时转换为ANSI,受制于ADestEncoding的可选ReadStringFromStream()参数。

© www.soinside.com 2019 - 2024. All rights reserved.