我对 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
参数)。
我收到 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
参数)。