Reading JSON POST using PHP

PhpJsonPost

Php Problem Overview


I looked around a lot before posting this question so my apologies if it is on another post and this is only my second quesiton on here so apologies if I don't format this question correctly.

I have a really simple web service that I have created that needs to take post values and return a JSON encoded array. That all worked fine until I was told I would need to post the form data with a content-type of application/json. Since then I cannot return any values from the web service and it is definitely something to do with how I am filtering their post values.

Basically in my local setup I have created a test page that does the following -

$curl = curl_init();
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");                                                                     
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);                                                                  
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);                                                                      
curl_setopt($curl, CURLOPT_HTTPHEADER, array(                                                                          
    'Content-Type: application/json',                                                                                
    'Content-Length: ' . strlen($data))                                                                       
);
curl_setopt($curl, CURLOPT_URL, 'http://webservice.local/');  // Set the url path we want to call
$result = curl_exec($curl);

//see the results
$json=json_decode($result,true);
curl_close($curl);
print_r($json);

On the webservice I have this (I have stripped out some of the functions) -

<?php

header('Content-type: application/json');

/* connect to the db */
$link = mysql_connect('localhost','root','root') or die('Cannot connect to the DB');
mysql_select_db('webservice',$link) or die('Cannot select the DB');

if(isset($_POST['action']) && $_POST['action'] == 'login') {
	$statusCode = array('statusCode'=>1, 'statusDescription'=>'Login Process - Fail');
	$posts[] = array('status'=>$statusCode);
	header('Content-type: application/json');
	echo json_encode($posts);

	/* disconnect from the db */
}
@mysql_close($link);

?>

Basically I know that it is due to the $_POST values not being set but I can't find what I need to put instead of the $_POST. I tried json_decode($_POST), file_get_contents("php://input") and a number of other ways but I was shooting in the dark a bit.

Any help would be greatly appreciated.

Thanks, Steve

Thanks Michael for the help, that was a definite step forward I now have at least got a repsonse when I echo the post....even if it is null

updated CURL -

  $curl = curl_init();
  curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); 
  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); 
  curl_setopt($curl, CURLOPT_URL, 'http://webservice.local/');  
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));

updated php on the page that the data is posted to -

$inputJSON = file_get_contents('php://input');
$input= json_decode( $inputJSON, TRUE ); //convert JSON into array

print_r(json_encode($input));

As I say at least I see a response now wheras prior it was returning a blank page

Php Solutions


Solution 1 - Php

You have empty $_POST. If your web-server wants see data in json-format you need to read the raw input and then parse it with JSON decode.

You need something like that:

$json = file_get_contents('php://input');
$obj = json_decode($json);

Also you have wrong code for testing JSON-communication...

CURLOPT_POSTFIELDS tells curl to encode your parameters as application/x-www-form-urlencoded. You need JSON-string here.

UPDATE

Your php code for test page should be like that:

$data_string = json_encode($data);

$ch = curl_init('http://webservice.local/');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Content-Type: application/json',
        'Content-Length: ' . strlen($data_string))
);

$result = curl_exec($ch);
$result = json_decode($result);
var_dump($result);

Also on your web-service page you should remove one of the lines header('Content-type: application/json');. It must be called only once.

Solution 2 - Php

Hello this is a snippet from an old project of mine that uses curl to get ip information from some free ip databases services which reply in json format. I think it might help you.

$ip_srv = array("http://freegeoip.net/json/$this->ip","http://smart-ip.net/geoip-json/$this->ip");

getUserLocation($ip_srv);

Function:

function getUserLocation($services) {
		
		$ctx = stream_context_create(array('http' => array('timeout' => 15))); // 15 seconds timeout

		for ($i = 0; $i < count($services); $i++) {
 
			// Configuring curl options
			$options = array (
				CURLOPT_RETURNTRANSFER => true, // return web page
				//CURLOPT_HEADER => false, // don't return headers
				CURLOPT_HTTPHEADER => array('Content-type: application/json'),
				CURLOPT_FOLLOWLOCATION => true, // follow redirects
				CURLOPT_ENCODING => "", // handle compressed
				CURLOPT_USERAGENT => "test", // who am i
				CURLOPT_AUTOREFERER => true, // set referer on redirect
				CURLOPT_CONNECTTIMEOUT => 5, // timeout on connect
				CURLOPT_TIMEOUT => 5, // timeout on response
				CURLOPT_MAXREDIRS => 10 // stop after 10 redirects
			); 

			// Initializing curl
			$ch = curl_init($services[$i]);
			curl_setopt_array ( $ch, $options );

			$content = curl_exec ( $ch );
			$err = curl_errno ( $ch );
			$errmsg = curl_error ( $ch );
			$header = curl_getinfo ( $ch );
			$httpCode = curl_getinfo ( $ch, CURLINFO_HTTP_CODE );

			curl_close ( $ch );
			
			//echo 'service: ' . $services[$i] . '</br>';
			//echo 'err: '.$err.'</br>';
			//echo 'errmsg: '.$errmsg.'</br>';
			//echo 'httpCode: '.$httpCode.'</br>';
			//print_r($header);
			//print_r(json_decode($content, true));

			if ($err == 0 && $httpCode == 200 && $header['download_content_length'] > 0) {

				return json_decode($content, true);
				
			} 
 
		}
	}

Solution 3 - Php

you can put your json in a parameter and send it instead of put only your json in header:

$post_string= 'json_param=' . json_encode($data);

//open connection
$ch = curl_init();

//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_POST, 1);
curl_setopt($ch,CURLOPT_POSTFIELDS, $post_string);
curl_setopt($curl, CURLOPT_URL, 'http://webservice.local/');  // Set the url path we want to call

//execute post
$result = curl_exec($curl);

//see the results
$json=json_decode($result,true);
curl_close($curl);
print_r($json);

on the service side you can get your json string as a parameter:

$json_string = $_POST['json_param'];
$obj = json_decode($json_string);

then you can use your converted data as object.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSteve MatthewsView Question on Stackoverflow
Solution 1 - PhpMichael SivolobovView Answer on Stackoverflow
Solution 2 - Php0x_AnakinView Answer on Stackoverflow
Solution 3 - Phpmorteza kavakebiView Answer on Stackoverflow