DEV Community

Vasile Stefirta πŸ‡²πŸ‡© ✈️ πŸ‡ΊπŸ‡Έ
Vasile Stefirta πŸ‡²πŸ‡© ✈️ πŸ‡ΊπŸ‡Έ

Posted on • Edited on

Catch and parse JSON Post data in PHP

A few days ago I've been working a project which, as many other projects out there today, communicates with some external APIs. At some point, in order to perform some tests, I had to write an API endpoint within my project itself to fake the actual external API. I need to mention that the external API was expecting application/json content type, so basically the curl setup looked like this:

<?php //... $ch = curl_init(); curl_setopt( $ch, CURLOPT_URL, $url ); curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true ); curl_setopt( $ch, CURLOPT_VERBOSE, true ); curl_setopt( $ch, CURLOPT_HEADER, true ); curl_setopt( $ch, CURLOPT_TIMEOUT, $this->timeout_limit ); curl_setopt( $ch, CURLOPT_ENCODING, '' ); curl_setopt( $ch, CURLOPT_MAXREDIRS, 10 ); curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, 'POST' ); curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( $data ) ); curl_setopt( $ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json' ) ); // ... 
Enter fullscreen mode Exit fullscreen mode

The issue was that when I've been trying to catch the POST data and use it, I was getting null as a value for both $_POST or $_REQUEST, and I couldn't understand why πŸ€”. Apparently (and maybe many of you already knew that), if the data is sent as multipart/form-data or application/x-www-form-urlencoded then yes, you can use PHP globals $_POST or $_REQUEST to catch and use that data. But, if the data is sent as application/json, then prior to PHP 5.6 you could've use $HTTP_RAW_POST_DATA to grab the raw POST data, or (and based on PHP docs this is the preferable way to do it) use the php://input - a read-only stream that allows you to read raw data from the request body.

So, as a result I ended up grabbing the POST data like this:

<?php // receive the JSON Post data $data = json_decode( file_get_contents( 'php://input' ), true ); 
Enter fullscreen mode Exit fullscreen mode

Big credits to these stackoverflow discussions:
https://stackoverflow.com/questions/2731297/file-get-contentsphp-input-or-http-raw-post-data-which-one-is-better-to
https://stackoverflow.com/questions/813487/how-to-post-json-to-php-with-curl/813512

Happy coding everyone! πŸ’» πŸ€“ πŸ‘

Top comments (6)

Collapse
 
aitorxs profile image
jose machuca

Hello! I am trying to send a json in the following way

$factura ->acciones = array('enviar_xml_firmado' => false );

$ch = curl_init($url);
$jsonDataEncoded = json_encode($factura);

curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json' , $authorization ));
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS,$jsonDataEncoded);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$result = curl_exec($ch);
curl_close($ch);
return json_decode($result);

but I get the error $HTTP_RAW_POST_DATA de php 5.6, in which part or in what form should I go
$data = json_decode( file_get_contents( 'php://input' ), true );

so that it works well?

Collapse
 
dev_nope profile image
Vasile Stefirta πŸ‡²πŸ‡© ✈️ πŸ‡ΊπŸ‡Έ

Hi there, were you able to solve the issue?

Collapse
 
mrcodekiddie profile image
Muthu Kumar • Edited

Just In Case, If anyone need this

<?php // Only allow POST requests $response=new stdClass(); //you may get a warning , otherwise . header('Content-Type: application/json'); //gonna send everything as JSON response.. so, anyways if (strtoupper($_SERVER['REQUEST_METHOD']) != 'POST') { http_response_code(405); $response->status="failed"; $response->message="Method Not Allowed"; echo json_encode($response); exit(); } // Make sure Content-Type is application/json $content_type = isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : ''; if (stripos($content_type, 'application/json') === false) { $response->status="failed"; $response->message="Content-Type must be application/json"; http_response_code(415); echo json_encode($response); exit(); } // Read the input stream $request_body = file_get_contents("php://input"); // Decode the JSON object $data = json_decode($request_body, true); // Throw an exception if decoding failed if (!is_array($data)) { $response->status="error"; $response->message="Invalid JSON"; http_response_code(400); echo json_encode($response); exit(); } 
Enter fullscreen mode Exit fullscreen mode
Collapse
 
parasdaryanani profile image
Paras Daryanani

Thanks Vasile, this really helped me. Working with a very old framework here that still uses PHP 5.6 and had this exact issue of $_POST being empty everytime I sent JSON.

Collapse
 
tmblog profile image
tmblog

Nice! Any headers etc to put in the receiving end in order to accept only post/json?

Collapse
 
dev_nope profile image
Vasile Stefirta πŸ‡²πŸ‡© ✈️ πŸ‡ΊπŸ‡Έ

You shouldn't need to. You only set the Content-Type: application/json when sending out the request.