为什么JSON的结果可能是布尔值,而不是对象或数组?数组、而不是、对象、结果

2023-09-11 01:18:39 作者:祖国滴粑粑花

从 JSON网站:

  

JSON是建立在两种结构:

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

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

 < PHP
标题(内容类型:应用程序/ JSON);
回声真;
出口;
 

和请求该页面使用Ajax时(例如使用jQuery):

  $。阿贾克斯({
    网址:service.php,
    数据类型:JSON,
    成功:功能(数据){
        的console.log(数据);
        的console.log(typeof运算的数据);
    }
});
 
Json数组转List

其结果将是:

   - >真正
 - >布尔
 

我的问题是,为什么它允许返回布尔作为一个JSON。 难道不是有冲突的JSON定义?

同时

我也可以返回号或字符串在我的服务:

 < PHP
标题(内容类型:应用程序/ JSON);
呼应'2013';
出口;
 

和结果是:

   - > 2013
 - >数
 

和字符串:

 < PHP
标题(内容类型:应用程序/ JSON);
回声这是怎么回事?;
出口;
 

和结果是:

   - >到底是怎么回事?
 - >串
 

解决方案

您是正确的,有效的JSON文本只能是一个对象或数组。我问道格拉斯·克罗克福德这个在2009年,他证实了它,说:严格来说,这是目标。|阵列,如在RFC

借助 JSON RFC 指定此节2:

  

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

  JSON文本=对象/数组
 

在 json.org 列出的原始JSON语法不明确这一点的。它定义了所有的JSON类型的,但它没有说的任何位置这些类型的可被用作JSON文本 - JSON的一个完整有效的片

这就是为什么我问道格呢,他叫我去的RFC。不幸的是,他并没有对我的建议跟进更新json.org澄清这一点。

这种混乱可能是因为

,许多JSON库将愉快地创建和解析(无效)JSON的独立字符串,数字,布尔值,等等。虽然这些都不是真正有效的JSON。

有些JSON解析器更加严格。例如, jsonlint.com 拒绝JSON文本,如 101 ABC。它只接受一个物体或阵列。

这个区别可能没有多大关系,如果你刚生成的JSON数据,消费在自己的Web应用程序。毕竟, JSON.parse()很高兴地分析它,并很可能在所有的浏览器也是如此。

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

我建议即使是在自己的应用程序下面的话,一方面是因为有一个实际的好处:通过发送一个裸字符串下来的对象,而不是,你有一个,如果你需要内置的地方加入更多的信息,在在对象的附加属性的形式。

根据这些原则,当我确定一个JSON API,我从来没有使用数组的最顶层。如果我有什么是某种类型的项目的数组,我还是把它包在一个对象:

  {
    项目:
        ...
    ]
}
 

这部分是出于同样的原因:如果我以后想别的东西添加到响应,其顶层是一个对象,使这很容易做到不破坏任何现有的客户端code

也许更重要的是,还有一个可能的security风险与JSON阵列。 (我的认为的风险仅影响使用的eval()功能构造解析JSON,所以你是安全与 JSON.parse(),但我不是100%肯定这一点。)

From JSON website:

JSON is built on two structures:

A collection of name/value pairs. In various languages, this is realized as an object, record, struct, dictionary, hash table, keyed list, or associative array. An ordered list of values. In most languages, this is realized as an array, vector, list, or sequence.

Now I have a sample service that returns a boolean (this is in PHP, but it could be any server side language):

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

And when requesting this page with ajax (for example with jQuery):

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

The result would be:

-> true
-> boolean

My question is why it's allowed to return boolean as a JSON. Doesn't it have conflict with JSON definition?

ALSO

Also I can return number or string in my service:

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

And the result is:

-> 2013
-> number

And for string:

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

And the result is:

-> What is going on?
-> string

解决方案

You are correct that a valid JSON text can only be an object or an array. I asked Douglas Crockford about this in 2009 and he confirmed it, saying "Strictly speaking, it is object|array, as in the RFC."

The JSON RFC specifies this in section 2:

A JSON text is a serialized object or array.

JSON-text = object / array

The original JSON syntax listed on json.org does not make this clear at all. It defines all of the JSON types, but it doesn't say anywhere which of these types may be used as a "JSON text" - a complete valid piece of JSON.

That's why I asked Doug about it and he referred me to the RFC. Unfortunately, he didn't follow up on my suggestion to update json.org to clarify this.

Probably because of this confusion, many JSON libraries will happily create and parse (invalid) JSON for a standalone string, number, boolean, etc. even though those aren't really valid JSON.

Some JSON parsers are more strict. For example, jsonlint.com rejects JSON texts such as 101, "abc", and true. It only accepts an object or array.

This distinction may not matter much if you're just generating JSON data for consumption in your own web app. After all, JSON.parse() is happy to parse it, and that probably holds true in all browsers.

But it is important if you ever generate JSON for other people to use. There you should follow the standard more strictly.

I would suggest following it even in your own app, partly because there's a practical benefit: By sending down an object instead of a bare string, you have a built-in place to add more information if you ever need to, in the form of additional properties in the object.

Along those lines, when I'm defining a JSON API, I never use an array at the topmost level. If what I have is an array of items of some sort, I still wrap it in an object:

{
    "items": [
        ...
    ]
}

This is partly for the same reason: If I later want to add something else to the response, having the top level be an object makes that easy to do without disrupting any existing client code.

Perhaps more importantly, there's also a possible security risk with JSON arrays. (I think that risk only affects the use of eval() or the Function constructor to parse JSON, so you're safe with JSON.parse(), but I'm not 100% sure on this.)