7

来自JSON 网站

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

我的问题是为什么允许将布尔值作为 JSON 返回。它与JSON定义没有冲突吗?


我也可以在我的服务中返回数字字符串:

<?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
4

2 回答 2

9

您是正确的,有效的 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。它只接受一个对象或数组。

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

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

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

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

{
    "items": [
        ...
    ]
}

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

也许更重要的是,JSON 数组也可能存在安全风险。(我认为这种风险只会影响解析 JSON 的使用eval()Function构造函数,因此您可以放心使用JSON.parse(),但我对此不是 100% 确定的。)

于 2013-06-06T06:41:38.177 回答
1

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

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

于 2019-06-07T11:52:11.610 回答