JSON是否可以以"["开头?

252

根据我在json.org上的阅读,所有JSON字符串都应以{(花括号)开头,并且[字符(方括号)代表JSON中的数组元素。

我使用了json4j库,我得到了一个以[开头的输入,因此我认为这不是有效的JSON。我简要地查看了JSON模式,但我无法找到它是否声明JSON文件不能以[开头,或者只能以{开头。


1
显然有几个设计不良的JSON库需要你知道最外层的JSON类型。这里最简单的“修复”方法是用[]包围JSON字符串,将其解析为数组,并取第一个数组元素。 - Hot Licks
2
显然,最好以 { 开头而不是 [,这样它就不是有效的Javascript数组,也不能用于CSRF攻击。 - David Klempfner
1
我们在2022年有一些在线验证器(例如https://jsonlint.com)。我们可以检查其有效性并获得有关问题的反馈。 - cansu
4个回答

294

JSON 可以是数组或对象。具体来说,来自 json.org 的定义如下:

JSON 基于两种结构:

  • 名称/值对的集合。在不同的语言中,这可以被实现为 对象、记录、结构体、字典、哈希表、关联列表等。
  • 有序值列表。在大多数语言中,这通常被实现为 数组、向量、列表或序列。

接下来描述了这两种结构的方式:

一个 JSON 对象 一个 JSON 数组

请注意,起始和结束字符分别是大括号和方括号。

编辑
另外从这里:http://www.ietf.org/rfc/rfc4627.txt

JSON 文本是一系列标记。标记集包括六个 结构字符、字符串、数字和三个文字名称。

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

更新(2014)

截至 2014 年 3 月,有一个新的 JSON RFC (7159) 稍微修改了定义 (详见第 4/5 页)。

RFC 4627 中的定义为: JSON-text = object / array

在 RFC 7159 中,这已被更改为: JSON-text = ws value ws

其中 ws 表示空格,value 的定义如下:

JSON 值必须是对象、数组、数字或字符串之一,或以下三个字面名称之一:

false null true
因此,对于这个问题的答案仍然是可以的,JSON文本可以以方括号(即数组)开头。但除了对象和数组之外,它现在还可以是数字、字符串或值falsenulltrue
另外,这与我先前引用的RFC 4627中不同(已加重强调):
一个JSON文本是一系列令牌。令牌集包括六个结构字符、字符串、数字和三个文字名称。
一个JSON文本是一个序列化。请注意,先前的某些JSON规范将JSON文本限制为对象或数组。在调用JSON文本时仅生成对象或数组的实现将在相互操作方面是可互换的,因为所有实现都将接受这些符合JSON格式的文本。

谢谢,我看了那个图很多次,显然json4j库有问题,它不喜欢带有[的JSON。 - Tiberiu
1
@Tiberiu Hajas:我第一次发现它时需要一点时间才能理解。但是在看到一些JSON的示例并进行比较后,我真的很喜欢他们的做法。关于json4j,也许你可以向json4j库的创建者提交错误报告。 - Richard Marskell - Drackir
我可能来晚了。但是我在RFC 8259中发现的内容说,JSON文本是由符合JSON值语法的Unicode代码点序列形成的令牌序列。令牌集包括六个结构令牌、字符串、数字和三个文字名称令牌。这听起来像是这样的东西是合法的:{"1234"},{true}。然而,这代表什么?这不是一个数组,因为没有<code>[]</code>,也不是一个对象,因为有两个它们。 - Nicholas Humphrey
1
@NicholasHumphrey,我上面写的在8259中仍然适用。在同一节2(JSON语法)中,JSON-text(又称为JSON文档)被定义为:“JSON-text = ws value ws”,其中“JSON值必须是对象、数组、数字或字符串,或以下三个文字名称之一:false、null、true”,根据第3节(值)。你的例子不满足这些约束条件,因此不是有效的JSON。 - Richard Marskell - Drackir
1
@Richard Marskell - Drackir:我一直在尝试找到JSON文件结构和所有规则的可视化表示。您的评论帮助我找到了我需要的东西。https://www.json.org/json-en.html 谢谢你,伙计。你的评论让我找到了我需要去的地方。 :) - GroggyOtter
所以,简单总结一下2014年的变化,有效的json过去只能是一个对象或数组,但现在它可以是一个对象、数组或简单值了? - jschmitter

12

如果您要解析的字符串以左大括号([)开头,则可以使用JSONArray.parse获取一个JSONArray对象,然后可以使用get(i),其中i是从0到返回的JSONArray的size()-1的索引。

import java.io.IOException;
import com.ibm.json.java.JSONArray;
import com.ibm.json.java.JSONObject;

public class BookListTest {
   public static void main(String[] args) {
      String jsonBookList = "{\"book_list\":{\"book\":[{\"title\":\"title 1\"},{\"title\":\"title 2\"}]}}";
      Object book_list;
      try {
         book_list = JSONObject.parse(jsonBookList);
         System.out.println(book_list);
         Object bookList = JSONObject.parse(book_list.toString()).get("book_list");
         System.out.println(bookList);
         Object books = JSONObject.parse(bookList.toString()).get("book");
         System.out.println(books);
         JSONArray bookArray = JSONArray.parse(books.toString());
         for (Object book : bookArray) {
            System.out.println(book);
         }
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
}

生成了如下输出:

{"book_list":{"book":[{"title":"title 1"},{"title":"title 2"}]}}
{"book":[{"title":"title 1"},{"title":"title 2"}]}
[{"title":"title 1"}, {"title":"title 2"}]
{"title":"title 1"}
{"title":"title 2"}

注意:如果你尝试调用 JSONObject.parse(books.toString());,你将会遇到你所遇到的错误:

java.io.IOException: Expecting '{' on line 1, column 2 instead, obtained token: 'Token: ['

2
更简单的代码可能会使用instanceof JSONArray而不是instanceof JSONObject来确定应该使用哪个类来解析返回的对象。 - Nathaniel Mills

11

JSON.ORG网站表示....

https://www.json.org/

该网站明确指出以下内容:

JSON基于两个结构:

  1. 一组名称/值对。在各种语言中,这被实现为对象、记录、结构、字典、哈希表、键列表或关联数组。

  2. 数值的有序列表。在大多数语言中,这被实现为数组、向量、列表或序列。

这些是通用数据结构。几乎所有现代编程语言都以某种形式支持它们。一个与编程语言可互换的数据格式也应该基于这些结构,这是有意义的。 在JSON中,它们采取如下形式:

对象:

一个对象是一组无序的名称/值对。对象以左花括号{开始,右花括号}结束。每个名称后跟着冒号:,名称/值对之间用逗号分隔。

{string: value, string: value}

数组:

数组是一个有序的值集合。一个数组以左括号 [ 开始,右括号 ] 结束。值之间用逗号 , 分隔。

[value, value, value ….]

数值:

数值可以是双引号括起来的字符串,也可以是数字、true、false、null、对象或数组。这些结构可以嵌套。

字符串:

字符串是一系列零个或多个 Unicode 字符,用双引号括起来,并使用反斜杠转义。一个字符被表示为一个单字符字符串。字符串非常类似于 C 或 Java 的字符串。

数字:

数字与 C 或 Java 数字非常相似,但不使用八进制和十六进制格式。

关于空格:

空格可以插入在任何一对标记之间。除了一些编码细节外,这完全描述了语言。


1
例子很好,它帮助我完成了JSON验证器的单元测试编写。我不确定字符串是什么意思(例如,它必须是双引号内的字符串)。 - gimlichael
我明白这可能会让人感到困惑,这句话可以更简洁地开始,如下所示:“零个或多个Unicode字符的序列...”我认为作者可能是为了强调而添加的。我将其排列在一起,以便更容易看到一些关键点。虽然回复有些晚,但希望如果需要的话能增加一些清晰度。 - J. Moreno

2
短答案是是的
在.json文件中,您可以放置数字(甚至只有10),字符串(甚至只有“hello”),布尔值(true,false),空(null,甚至只是null),数组和对象。 https://www.json.org/json-en.html 仅使用数字、字符串、布尔值和空不太合理,因为在.json文件中,我们使用更复杂的结构化数据,如数组和对象(大多数为混合嵌套版本)。
下面您可以找到一个带有对象数组的样本JSON数据,并以“[”开头。 https://jsonplaceholder.typicode.com/posts

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接