7

Anybody getting JSON to work with TIdHttp ?

The PHP always return NULL in the $_POST, am I doing anything wrong ?

Delphi source:

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 source:

<?php
$value = json_decode($_POST);
var_dump($value);
?>
Atlas
  • 1,333
  • 5
  • 18
  • 31

2 Answers2

9

You can't use a TStringList to post JSON data. TIdHTTP.Post() will encode the TStringList contents in a way that breaks the JSON data. You need to put the JSON data into a TStream instead. TIdHTTP.Post() will transmit its contents as-is. Also, don't forget to set the TIdHTTP.Request.ContentType property so the server knows you are posting JSON data.

Remy Lebeau
  • 454,445
  • 28
  • 366
  • 620
  • 3
    Your answer was the correct answer, though. To post raw JSON data and have it accepted using the original PHP code, a `TStream` needs to be used instead of a `TStringList`, just like you showed. The only error in your answer is you are setting `Request.ContentEncoding` to UTF-8, which is wrong because UTF-8 is not a valid content encoding. It belongs in `Request.CharSet` instead. – Remy Lebeau Aug 31 '12 at 00:01
  • Remy, I accepted the above becoz it seemed to work, but not sure in the long run. `TIdHTTP.Request.ContentType` should be to `application/json`? Also, do you mean I can opt out the `json=` part? – Atlas Aug 31 '12 at 04:21
  • @RemyLebeau, I changed it as you suggested (see code above) using `TStringStream`. I still get `NULL` from `json_decode($_POST)` though. – Atlas Sep 02 '12 at 11:47
  • 3
    I did a little research and found the original PHP script is wrong in using `$_POST` in the first place. That only works when posting name/value pairs, which the JSON stream is not. The PHP script needs to use `php://input` instead to access the raw JSON data, eg: `$value = json_decode(file_get_contents('php://input'));` – Remy Lebeau Sep 02 '12 at 17:28
3

You need to define a post variable, try this code (I have added "json" var to your code):

Delphi code:

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 source:

<?php
$value = json_decode($_POST['json']);
var_dump($value);
?>
sgomez
  • 31
  • 2
  • I still get NULL, but when I do "var_dump($_POST)" I get the array. Any ideas? – Atlas Aug 30 '12 at 06:14
  • Have you tried to trace what's going out of your application e.g. using WireShark or similar tools ? I don't know anything about the PHP part, but at least your Delphi part have some issues. – TLama Aug 30 '12 at 08:30
  • Seemed the slashes were the culprit, I changed it to `$value = stripcslashes($_POST['json'])`, now working fine – Atlas Aug 30 '12 at 11:15
  • 1
    @Atlas, try to learn how to use safe `try..finally` blocks. In your code as well as in this post, the `IdHTTP` may fail because Indy is driven by exceptions, what may easily cause memory leaks in your application. And anyway, does your code work without change of the request content type ? – TLama Aug 30 '12 at 12:21
  • @TLama, yes I will use the `try..finally`, the source above is just for a simpler view, not the production version. Yes, it seemed to work without ContentType, which was weird... Sometimes Indy drives me crazy... – Atlas Aug 31 '12 at 04:27