背景:
因此,我编写了以下PHP代码片段来帮助我调试一个更大的问题,但现在我更困惑于jQuery和PHP如何发送/接收JSON,因为这段代码似乎没有达到我的预期:
我希望能够接收数据作为application/x-www-form-urlencoded
或作为application/json
,同时仅使用application/json
进行响应(目前)。
test.php
:
<?php
$content_type = $_SERVER['CONTENT_TYPE'];
switch ($_SERVER['REQUEST_METHOD']) {
case 'GET':
echo <<< _EOF
<html>
<body>
<div id="content"></div>
<script type="text/javascript" src="/jquery-1.10.2.min.js"></script>
</body>
</html>
_EOF;
break;
case 'POST':
header('Content-type: application/json');
if ($content_type == 'application/x-www-form-urlencoded') {
$_POST['message'] = 'debugged';
echo json_encode($_POST);
# Otherwise, get raw body data.
} else {
$data = file_get_contents('php://input');
if ($data == null) {
$data = file_get_contents('php://stdin');
}
$object = json_decode($data, true);
$object['message'] = 'debugged';
echo json_encode($object);
}
break;
default:
echo "These aren't the droids you're looking for. Move along.<br />";
break;
}
测试:
我一直在使用Python请求库和jQuery的Ajax方法测试这段代码。
在Python中,数据可以作为application/x-www-form-urlencoded
发送,也可以作为附加到请求的原始主体数据发送,具体取决于为post()
方法提供的data
参数的类型(有关更多信息,请参阅此处)。
到目前为止一切顺利
使用请求,我得到了我所期望的。
当post()
方法的data
参数是Python字典对象时,数据以编码形式发送:
>>> import requests
>>> r = requests.post('http://example.com/test.php', data={"name": "tester", "message": "bug"})
>>> print r.text
{"message": "debugged", "name": "tester"}
当data
参数是文本字符串(注意单引号!)时,数据将作为请求的主体发送,并且可能(也可能不)在端点被解释为JSON(我在上面的示例PHP代码中确实将其解释为JSON,并且保证它永远只是JSON):
>>> r = requests.post('http://example.com/test.php', data='{"name": "tester", "message": "bug"}')
>>> print r.text
{"message": "debugged", "name": "tester"}
这两个结果都是我所期望的。
这是奇怪的部分
我似乎从这段代码中得到了不同的响应,这并不取决于我如何发送数据,而是我用什么发送数据(即请求或jQuery)。这两者之间一定有什么不同之处,我完全不知道。
如果我将浏览器(Chrome)指向http://example.com/test.php,触发GET请求处理程序为我提供上面PHP代码中包含的微小HTML页面,然后在JavaScript控制台中启动以下jQuery代码,这就是我得到的结果:
> var output = null;
> $.ajax({
type: 'POST',
url: 'http://example.com/test.php',
data: {
name: 'tester',
message: 'bug'
},
dataType: 'json',
beforeSend: function(x) {
if (x && x.overrideMimeType) {
x.overrideMimeType('application/json; charset=UTF-8');
}
},
success: function(d) {
$output = d;
}
});
> output
Object {message: "debugged"}
现在我在想,"名字"条目到底去了哪里
事实证明,只有我在PHP处理程序中显式设置的东西似乎可以作为jQuery的输出访问。但有时我想使用来自用户输入的数据,对其进行修改,然后将其作为输出返回。但由于jQuery的行为是这样的,(或者PHP……我不太确定我的错误在哪一段代码中)我无法做我想做的事情。
更奇怪
我做的下一件事是根据POST处理程序中的if语句是输入的还是"elsed",将输出消息更改为"debugged(表单数据)"或"debuggeed(主体数据)",并惊讶地发现jQuery将数据作为主体数据发送,但正在设置application/x-www-form-urlencoded
标头这完全不是我所期望的。我觉得jQuery(1.10.2)或Python请求中的任何一个都因为这种差异而行为不端,但我不确定是哪一个。(或者发送表单编码的数据真的是这种特殊的吗?)
如果对这里发生的事情有任何想法或见解,我错过了什么,如果我的期望或错误,我应该期待什么,甚至是我在研究这件事时忽略的相关文档的链接,我们将不胜感激。
是否尝试将标识符"name"置于引号中。这是一个保留字,有些解析器无法很好地处理它不在引号中的问题。几年前我也遇到过类似的问题。