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
 
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
 
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
 
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.