使用 contentType 的 Ajax 调用:'application/json' 不起作用

Posted

技术标签:

【中文标题】使用 contentType 的 Ajax 调用:\'application/json\' 不起作用【英文标题】:Ajax call with contentType: 'application/json' not working使用 contentType 的 Ajax 调用:'application/json' 不起作用 【发布时间】:2013-12-16 04:48:36 【问题描述】:

我有一个 ajax 调用,它将表单数据发送到一个 php 函数。因为我读了很多,使用contentType: 'application/json' 是最佳实践,所以我也想尝试一下。但不幸的是,当我使用它时,我的脚本没有返回任何内容。如果我删除它,脚本会做它应该做的事情。

您知道原因可能是什么以及为什么?谢谢!

$('#Form').submit(function(e) 
            e.preventDefault();

            var content = $(this).serialize() + "&ajax=1";

            $.ajax('app/class/controller/contactForm.php', 
              type: "POST",
              //contentType: 'application/json',
              dataType: 'json',
              data: content,
              success: function(result) 
                  console.log(result);
              
            );
        )

还有我的 PHP:

if(isset($_POST['ajax']) && $_POST['ajax'] === '1') 
    echo json_encode(validateForm($_POST));

【问题讨论】:

如果没有它也能正常工作,你为什么觉得有必要添加它? 类似***.com/questions/17194251/… contentType 指定您正在发送,而不是接收的数据的格式。您发送数据的格式是正常的查询字符串格式。 【参考方案1】:

使用contentType: 'application/json' 时,您将无法依赖$_POST 被填充。 $_POST 仅为表单编码的内容类型填充。

因此,您需要从 PHP 原始输入中读取数据,如下所示:

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

当然,如果您想发送application/json,您实际上应该发送 JSON,但您并没有这样做。您要么需要将对象序列化直接构建为 JSON,要么需要执行类似的操作 - Convert form data to javascript object with jQuery - 从表单中序列化对象。

老实说,在您的情况下,由于您正在处理表单数据,我不太认为使用 application/json 的用例存在。

【讨论】:

谢谢!我想这是问题的根源。我看到一些例子是表单数据被序列化并设置了 contentType。这就是为什么我认为它应该是这样的。 @Sebsemillia 当然,如果您想要使用 JSON,PHP 没有理由无法响应 JSON。这实际上可能归结为您如何使用 javascript 来确定您希望如何在 PHP 中发布和处理数据。例如,如果你有一个不错的 javascript 对象,你想 POST 到 PHP。序列化为 JSON 并使用application/json 发送将是微不足道的,这样 PHP 可以简单地解码对象并使用它。 感谢您解释未填充 $_POST 的问题。这是我正在寻找的信息。 你的回答在几个小时后对我有很大帮助,虽然我有 json_decode 而不是 json_encode,因为数据已经是 json 格式,所以你需要对其进行解码..所以这就是我所拥有的 $rawPostData = file_get_contents( 'php://输入'); $json = json_decode($rawPostData);【参考方案2】:

您提到的最佳实践是关于服务器脚本将 JSON 的 Content-Type 设置为“application/json”:

Header('Content-Type: application/json; charset=UTF8');

这是因为否则会发送默认的Content-Type,通常是包罗万象的text/html,这可能会导致客户不理解。

如果您在 jQuery 请求中为自己指定一个 Content-Type,jQuery 将确定最合适的一个。这里的问题是您发送了一个POST 表单,jQuery 设置的默认Content-Typeapplication/x-www-form-urlencoded,它告诉PHP 将数据解码为POST 字段并填充@987654330 @。然后,您的脚本会从 $_POST(或者可能是 $_REQUEST)恢复其参数。

通过将其更改为application/json$_POST 将不再被填充,接收脚本操作将无法接收到预期的参数,并且操作中断。

所以你要么需要:

不要自己指定 Content-Type(更好,恕我直言) 设置内容类型为application/x-www-form-urlencoded; charset=UTF-8 设置Content-Type为application/json; charset=UTF-8,修改脚本解析POST流,解码JSON数据;见this answer。

第三个选项需要proper handling 或php://input

【讨论】:

我明白了。这可能是问题所在。非常感谢! @Isemi 关于内容类型的评论是正确的。您关于未设置 content-Type 标头的信息不正确。大多数 HTTP 通信都应设置此设置。这只是让接收客户端知道发送数据的格式。在对服务器进行 AJAX 调用的情况下,服务器是接收客户端。浏览器绝对应该设置 Content-Type 标头,以便服务器知道会发生什么。在这种情况下,由于这种情况正在发生,服务器期待 JSON 并且没有像表单编码的 Content-Type 那样构建 $_POST @Isemi 同样,当服务器向 javascript 客户端发送响应时,它应该按照您的建议设置 Content-Type 标头。这告诉浏览器客户端期望的格式是什么。总而言之,应该为客户端到服务器的调用和服务器到客户端的响应声明 Content-Type。 @MikeBrant,是的,我知道这些问题;我的回答很糟糕。更新答案,即使我赞成你的:-) 非常感谢。您为“正确处理 php://input”提供的链接在数小时后为我解决了这个问题。 :)【参考方案3】:

PHP 脚本应该设置 Content-Type 标头。

if(isset($_POST['ajax']) && $_POST['ajax'] === '1') 
    header('Content-Type: application/json');
    echo json_encode(validateForm($_POST));

【讨论】:

嗯,不幸的是它仍然无法正常工作。我只是得到一个空的回复。 PHP 脚本应该发送这样的标头是正确的,但这与此问题无关,即通过将 application/json 设置为对 PHP 的初始 AJAX 调用的内容类型, PHP 未构建 $_POST。还有一个问题是他根本没有发送 JSON,而是一个 url 编码的查询字符串,正如典型的表单编码 POST 所期望的那样

以上是关于使用 contentType 的 Ajax 调用:'application/json' 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

在 AngularJS 中重写 jQuery Ajax 调用

使用Ajax调用填充html列表

ajax 调用 webService

JQuery使用Ajax调用后台方法

JQuery使用Ajax调用后台方法

ajax 调用会话超时