【问题标题】:Why JSON result could be boolean instead of object or array?为什么 JSON 结果可以是布尔值而不是对象或数组?
【发布时间】:2013-06-06 06:33:44
【问题描述】:

来自JSON website

JSON 建立在两种结构之上:

  • 名称/值对的集合。在各种语言中,这被实现为对象、记录、结构、字典、哈希表、键控列表或关联数组。
  • 值的有序列表。在大多数语言中,这被实现为数组、向量、列表或序列。

现在我有一个返回布尔值的示例服务(这是在 PHP 中,但它可以是任何服务器端语言):

<?php
header('Content-Type: application/json');
echo 'true';
exit;

当使用 ajax 请求此页面时(例如使用 jQuery):

$.ajax({
    url: 'service.php',
    dataType: 'json',
    success: function (data) {
        console.log(data);
        console.log(typeof data);
    }
});

结果是:

-> true
-> boolean

我的问题是为什么允许将 boolean 作为 JSON 返回。 和 JSON 定义不冲突吗?


我还可以在我的服务中返回 numberstring

<?php
header('Content-Type: application/json');
echo '2013';
exit;

结果是:

-> 2013
-> number

对于字符串:

<?php
header('Content-Type: application/json');
echo '"What is going on?"';
exit;

结果是:

-> What is going on?
-> string

【问题讨论】:

  • 它作为json返回以允许跨站点ajax请求
  • 如果你只能返回数组或对象,这些集合的内容会是什么?你最终需要标量对象作为叶子。
  • @Barmar - 根据RFC,“JSON 文本”只能是数组或对象。但是,该数组或对象中,您可以使用任何其他 JSON 数据类型。
  • 相关(如果不重复):stackoverflow.com/q/18419428/11683

标签: javascript ajax json


【解决方案1】:

您是正确的,有效的 JSON 文本只能是对象或数组。我在 2009 年向 Douglas Crockford 询问了这个问题,他证实了这一点,并说“严格来说,它是对象|数组,就像 RFC 中一样。”

JSON RFC 在第 2 节中指定了这一点:

JSON 文本是一个序列化的对象或数组。

JSON-text = object / array

json.org 上列出的原始 JSON 语法根本没有说明这一点。它定义了所有的 JSON 类型,但没有说明这些类型中的哪一种可以用作“JSON 文本”——一段完整的有效 JSON。

这就是我向 Doug 询问这件事的原因,他将我推荐给 RFC。不幸的是,他没有跟进我更新 json.org 以澄清这一点的建议。

可能由于这种混淆,许多 JSON 库会很乐意为独立的字符串、数字、布尔值等创建和解析(无效)JSON,即使这些不是真正有效的 JSON。

一些 JSON 解析器更加严格。例如,jsonlint.com 拒绝 JSON 文本,例如 101"abc"true。它只接受一个对象或数组。

如果您只是在自己的网络应用程序中生成 JSON 数据以供使用,那么这种区别可能并不重要。毕竟,JSON.parse() 很乐意解析它,这可能适用于所有浏览器。

但是,如果您曾经生成 JSON 供其他人使用,这一点很重要。在那里你应该更严格地遵循标准。

我建议即使在您自己的应用程序中也遵循它,部分原因是它有一个实际的好处:通过发送一个对象而不是一个裸字符串,您可以在需要时添加更多信息,在对象中附加属性的形式。

按照这些思路,当我定义 JSON API 时,我从不在最顶层使用数组。如果我拥有的是某种类型的项目数组,我仍然将它包装在一个对象中:

{
    "items": [
        ...
    ]
}

这部分是出于相同的原因:如果我以后想在响应中添加其他内容,将顶层作为对象可以很容易地做到这一点,而不会破坏任何现有的客户端代码。

也许更重要的是,还有一个可能的security risk with JSON arrays。 (我认为这种风险只会影响使用 eval()Function 构造函数来解析 JSON,所以使用 JSON.parse() 是安全的,但我对此不是 100% 确定.)

【讨论】:

  • JSON 数组的安全风险来自浏览器本身解析 JSON 的 CSRF 上下文——通过脚本标签获取,使用用户会话跨域! ——作为 JS。也就是说,安全风险不在于脚本本身(假设它获取同源数据),而在于 数据 的隐私。 [或者也许应该说风险“是”......我认为浏览器现在已经关闭了这样的副作用。]
  • @natevw - JSON 数组漏洞与数据隐私无关,这意味着作为 JSON 数组的数据本身也是有效的 javascript,浏览器最终可能会执行实际代码而不是反序列化.永远不要将 JSON 数组作为根数据返回的主要原因,而是更喜欢带有“items”键的对象。
  • @AdrianCrețu 请查看链接的讨论。 因为 JSON 数组是有效的 JavaScript,通过 CORS 绕过存在 [曾经?] 隐私风险。这个链接(来自其他问答中的 cmets)解释最直接:haacked.com/archive/2009/06/25/json-hijacking.aspx
  • @AdrianCrețu ...更不用说,如果您不信任服务器提供“安全”数组,您也不应该相信它与您对对象的“偏好”。问题之一是跨域隐私(数组从您域上的用户会话泄漏到恶意会话),不是不受信任的数据。
  • @natevw - 部分同意你的看法。然而,JSON 对象本身不是有效的 JavaScript 代码,而数组是。那里有很大的不同,主要是微软自己将所有 JSON 代理数据包装在他们的一些库中以嵌入 JSON 对象中的原因,无论你是否撒谎:)
【解决方案2】:

请注意,自 2013 年 rfc7158 以来,Michael Geary 的答案已经过时,不再将 JSON 文本限制为数组或对象。当前的 RFC https://www.rfc-editor.org/rfc/rfc8259 说:

JSON 文本是一个序列化值。请注意,某些先前的 JSON 规范将 JSON 文本限制为对象或 大批。仅生成对象或数组的实现 要求 JSON 文本将是可互操作的,因为所有 实现将接受这些作为符合 JSON 文本。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-19
  • 2022-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-29
  • 1970-01-01
相关资源
最近更新 更多