使用PHP读取JSON POST数据

62

在发布这个问题之前,我浏览了很多内容,所以如果这个问题已经在其他帖子中出现,那么请原谅,这是我在这里的第二个问题,所以如果我没能正确格式化这个问题,请原谅。

我创建了一个非常简单的 Web 服务,需要接收 post 值并返回 JSON 编码数组。一切都很顺利,直到有人告诉我我需要使用 content-type 为 application/json 发送表单数据。从那时起,我就无法从 Web 服务返回任何值,这明显与我如何过滤他们的 post 值有关。

基本上,在我的本地设置中,我创建了一个测试页面,执行以下操作 -

$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);

在我们的网络服务中,我有如下代码(已删除一些函数)-

<?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);

?>

基本上,我知道这是由于$_POST的值未被设置,但我找不到需要替换$_POST的内容。我尝试了json_decode($_POST)、file_get_contents("php://input")和其他一些方法,但有点盲目。

如果有任何帮助,将不胜感激。

谢谢,Steve

感谢Michael的帮助,这是一个明显的进步,当我回显post时,我现在至少得到了一个响应....即使它是null

更新的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));

更新了接收数据页面的 PHP 版本 -

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

print_r(json_encode($input));

至少现在我能看到有回应了,而之前它只会返回一张空白页面。


不确定失败原因,但我认为第一步应该是打印出 $_POST 的内容以查看其中的信息。如果数据存在,那么处理它们就相当容易了。如果 $_POST 为空,至少你知道问题出在哪里了。 - Sylverdrag
3个回答

129

您的$_POST为空。如果您的Web服务器想要查看JSON格式的数据,则需要读取原始输入,然后使用JSON解码进行解析。

您需要类似于以下内容:

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

同时,您的测试 JSON 通信的代码有误...

CURLOPT_POSTFIELDS 告诉 curl 将您的参数编码为 application/x-www-form-urlencoded。在此处需要 JSON 字符串。

更新

您用于测试页面的 PHP 代码应该像这样:

$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);

在您的网络服务页面上,您应该删除其中一行header('Content-type: application/json');。它只能被调用一次。


谢谢Michael,你的帮助很大,你能看一下我的编辑并查看是否还有其他导致问题的地方吗? - Steve Matthews
1
太有用了!这段代码:$json = file_get_contents('php://input'); $obj = json_decode($json);完美地运行了。 - Cleversou
我原本很害怕要花整天的时间来完成这个任务...但是太酷了,第一次尝试 less than 2min 就成功了!非常感谢,现在我可以假装很辛苦并且放一天假了... - Shadoweb
如果我使用 $json = file_get_contents('php://input'); 和 $obj = json_decode($json, true); 这段代码,就能帮助我了。否则我会遇到错误 "Cannot use object of type stdClass as array"。我发送的 $data 是一个作为 JSON 格式的对象。 - romanown

1

你好,这是我一个旧项目的片段,它使用curl从一些免费的IP数据库服务中获取IP信息,这些服务以JSON格式回复。我认为它可能会对你有所帮助。

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

getUserLocation($ip_srv);

功能:

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);

            } 

        }
    }

感谢您提供的代码片段,但我认为我的问题在于webservice / PHP方面,而不是CURL代码(虽然请随时告诉我是否如此,因为我不确定)。 我认为问题出在我的PHP $ _POST值上,无论它们是否需要进行json编码或其他处理。 - Steve Matthews
嗯,尝试将以下内容添加到您的curl中:curl_setopt($curl, CURLOPT_UPLOAD, 1); - 0x_Anakin

0

你可以将你的 JSON 放在一个参数中发送,而不是仅将 JSON 放在头部中:

$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);

在服务端,您可以将JSON字符串作为参数获取:

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

然后,您可以将转换后的数据用作对象。


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