Delphi TIdhttp如何发送JSON数据?

7

有人能够使用TIdHttp获取JSON数据吗?

PHP总是在$_POST中返回NULL,我做错了什么吗?

Delphi源代码:

http := TIdHttp.Create(nil);
http.HandleRedirects := True;
http.ReadTimeout := 5000;
http.Request.ContentType := 'application/json';
jsonToSend := TStringStream.Create('{"name":"Peter Pan"}');
jsonToSend.Position := 0;
Memo1.Lines.Text := http.Post('http://www.website.com/test.php', jsonToSend);
jsonToSend.free;
http.free;

PHP源代码:

<?php
$value = json_decode($_POST);
var_dump($value);
?>

1
考虑使用 var_dump($_POST) 查看您要求程序解码的内容。 - Rob Kennedy
对于这段代码,var_dump($_POST) 会输出 array(0) {} - Atlas
2个回答

9
您不能使用 TStringList 来发布JSON数据。 TIdHTTP.Post() 将以一种破坏JSON数据的方式编码 TStringList 的内容。 您需要将JSON数据放入 TStream 中。 TIdHTTP.Post() 将传输其内容,不做任何更改。 同时,请勿忘记设置 TIdHTTP.Request.ContentType 属性,以便服务器知道您正在发布JSON数据。

3
您的答案是正确的,要发布原始的JSON数据并使用原始的PHP代码接受它,需要使用TStream而不是TStringList,就像您展示的那样。 您答案中唯一的错误是将Request.ContentEncoding设置为UTF-8,这是错误的,因为UTF-8不是有效的内容编码方式。 它应该属于Request.CharSet - Remy Lebeau
Remy,我接受了上面的内容,因为它似乎可以工作,但长期来看不确定。TIdHTTP.Request.ContentType 应该是 application/json 吗?此外,您的意思是我可以选择退出 json= 部分吗? - Atlas
@RemyLebeau,我按照您的建议进行了更改(请参见上面的代码),使用了TStringStream。但是,我仍然从json_decode($_POST)中得到了NULL - Atlas
3
经过一番调查研究,我发现原始的PHP脚本在使用 $_POST 方面存在问题。这种方法只适用于提交名称/值对,而JSON流不是这样的。PHP脚本需要使用 php://input 来访问原始的JSON数据,例如:$value = json_decode(file_get_contents('php://input')); - Remy Lebeau

3
您需要定义一个POST变量,尝试使用以下代码(我已将“json”变量添加到您的代码中):
Delphi代码:
http := TIdHttp.Create(nil);
http.HandleRedirects := true;
http.ReadTimeout := 5000;
jsonToSend := TStringList.create;
jsonToSend.Text := 'json={"name":"Peter Pan"}';
Memo1.Lines.Text := http.Post('http://www.website.com/test.php', jsonToSend);
jsonToSend.free;
http.free;

PHP源代码:

<?php
$value = json_decode($_POST['json']);
var_dump($value);
?>

我仍然得到NULL,但是当我执行“var_dump($ _POST)”时,我会得到数组。有任何想法吗? - Atlas
你尝试过追踪应用程序的输出吗?例如使用WireShark或类似工具?我不知道PHP部分的情况,但至少你的Delphi部分存在一些问题。 - TLama
似乎是反斜杠引起的问题,我将其更改为$value = stripcslashes($_POST['json']),现在正常工作。 - Atlas
1
@Atlas,请尝试学习如何使用安全的try..finally块。在您的代码以及本帖中,IdHTTP可能会失败,因为Indy由异常驱动,这很容易导致应用程序中的内存泄漏。而且,您的代码是否可以在不更改请求内容类型的情况下正常工作? - TLama
@TLama,是的,我会使用try..finally,上面的代码只是为了更简单地展示,不是生产版本。是的,没有ContentType似乎也可以工作,这很奇怪...有时Indy让我发疯... - Atlas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接