Может ли JSON начинаться с «[»?

178

Из того, что я могу прочитать на json.org , все строки JSON должны начинаться с {(фигурные скобки), а [символы (квадратные скобки) представляют элемент массива в JSON.

Я использую json4jбиблиотеку, и я получил ввод, который начинается с [, поэтому я не думал, что это был правильный JSON. Я кратко посмотрел на схему JSON, но на самом деле не смог найти в ней заявления о том, что файл JSON не может начинаться [или может начинаться только с него {.

Тибериу
источник
(Очевидно, есть несколько плохо спроектированных библиотек JSON, которые требуют, чтобы вы знали самый внешний тип JSON. Самое простое «исправление» здесь - это окружить строку JSON [], проанализировать ее как массив и взять первый элемент массива.)
Hot Licks
По-видимому, безопаснее начинать с {, а не с [, чтобы он не был допустимым массивом Javascript и не мог использоваться для CSRF-атак.
Дэвид Клемпфнер

Ответы:

218

JSON может быть массивом или объектом. Специально от json.org:

JSON построен на двух структурах:

  • Коллекция пар имя / значение. На разных языках это реализовано как объект, запись, структура, словарь, хеш-таблица, список ключей или ассоциативный массив.
  • Упорядоченный список значений. В большинстве языков это реализовано как
    массив, вектор, список или последовательность.

Затем он описывает две структуры как: Объект JSON Массив JSON

Обратите внимание, что начальный и конечный символы - это фигурные и квадратные скобки соответственно.

Редактировать
И отсюда: http://www.ietf.org/rfc/rfc4627.txt

Текст JSON - это последовательность токенов. Набор токенов включает шесть структурных символов, строки, числа и три литеральных имени.

Текст JSON - это сериализованный объект или массив.

Обновление (2014)

По состоянию на март 2014 года появился новый RFC JSON ( 7159 ), который слегка изменяет определение (см. Стр. 4/5).

Определение согласно RFC 4627 было: JSON-text = object / array

Это было изменено в RFC 7159 на: JSON-text = ws value ws

Где wsпредставляет собой пустое пространство , и valueопределяется следующим образом :

Значение JSON ДОЛЖНО быть объектом, массивом, числом или строкой или одним из следующих трех литеральных имен:

false null true

Таким образом, ответ на вопрос все еще да, текст JSON может начинаться с квадратной скобки (то есть массива). Но в дополнение к объектам и массивам теперь это может быть также число, строка или значения false, nullили true.

Кроме того, это изменилось по сравнению с моей предыдущей цитатой RFC 4627 (выделение добавлено):

Текст JSON - это последовательность токенов. Набор токенов включает шесть структурных символов, строки, числа и три литеральных имени.

Текст JSON является сериализованным значением . Обратите внимание, что некоторые предыдущие спецификации JSON ограничивали текст JSON объектом или массивом. Реализации, которые генерируют только те объекты или массивы, для которых требуется текст JSON, будут совместимы в том смысле, что все реализации будут принимать их как соответствующие тексты JSON.

Ричард Марскелл - Дракир
источник
спасибо, я смотрю на эту цифру много раз, очевидно, есть проблема с библиотекой json4j, которая не любит json с [.
Тибериу
1
@ Тибериу Хаджас: Мне понадобилось немного времени, чтобы понять это, когда я впервые нашел это. Но после просмотра нескольких примеров JSON и их сравнения мне очень понравилось, как они это сделали. Что касается json4j, возможно, вы можете отправить отчет об ошибке создателю библиотеки json4j .
Ричард Марскелл - Дракир
Я, наверное, опаздываю на вечеринку. Но то, что я нашел в RFC 8259, говорит о том, что текст JSON - это последовательность токенов, сформированная из кодовых точек Unicode, которая соответствует грамматике значений JSON. Набор токенов включает в себя шесть структурных токенов, строки, числа и три токена буквальных имен. Это звучит так, как будто это законно: {"1234"}, {true}. Однако что это представляет? Это не массив, потому что нет <code> [] </ code>, и при этом это не объект, потому что их два.
Николас Хамфри
1
@NicholasHumphrey То, что я написал выше, все еще применяется в 8259. В том же разделе 2 (грамматика JSON) JSON-текст (он же документ JSON) определяется как: JSON-text = ws value wsгде «значение JSON ДОЛЖНО быть объектом, массивом, числом или строкой, или одно из следующих трех буквенных имен: false, null, true "в Разделе 3 (Значения). Ваш пример не удовлетворяет этим ограничениям и поэтому не является допустимым JSON.
Ричард Марскелл - Дракир
8

Если строка, которую вы анализируете, начинается с левой фигурной скобки ([), которую вы можете использовать, 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: ['
Натаниэль Миллс
источник
1
Более простой код может использовать экземпляр JSONArray вместо экземпляра JSONObject для объекта, возвращенного из вызова get, чтобы определить, какой класс следует использовать для анализа объекта ...
Натаниэль Миллс
5

ВЕБ-САЙТ JSON.ORG ГОВОРИТ ....

https://www.json.org/

На сайте четко указано следующее:

JSON построен на двух структурах:

  1. Коллекция пар имя / значение. На разных языках это реализовано как объект, запись, структура, словарь, хеш-таблица, список ключей или ассоциативный массив.

  2. Упорядоченный список значений. В большинстве языков это реализовано как массив, вектор, список или последовательность.

Это универсальные структуры данных. Практически все современные языки программирования поддерживают их в той или иной форме. Имеет смысл, чтобы формат данных, который взаимозаменяем с языками программирования, также был основан на этих структурах. В JSON они принимают следующие формы:

ОБЪЕКТ:

Объект - это неупорядоченный набор пар имя / значение. Объект начинается с {(левая скобка) и заканчивается} (правая скобка). Каждое имя сопровождается: (двоеточие), а пары имя / значение разделяются, (запятая).

{string: value, string: value}

ARRAY:

Массив - это упорядоченная коллекция значений. Массив начинается с [(левая скобка) и заканчивается] (правая скобка). Значения разделяются, (запятая).

[value, value, value ….]

СТОИМОСТЬ:

Значением может быть строка в двойных кавычках, или число, или true, или false, или null, или объект или массив. Эти структуры могут быть вложенными.

STRING:

Строка - это последовательность из нуля или более символов Юникода, заключенная в двойные кавычки с использованием обратной косой черты. Символ представляется в виде отдельной символьной строки. Строка очень похожа на строку C или Java.

ЧИСЛО:

Число очень похоже на число C или Java, за исключением того, что восьмеричный и шестнадцатеричный форматы не используются.

О ПУТИ:

Пробелы могут быть вставлены между любой парой токенов. За исключением нескольких деталей кодирования, которые полностью описывают язык.

Дж. Морено
источник
Хорошо с примерами; это помогло мне закончить написание модульного теста для валидатора JSON. Я не был уверен, что подразумевается под строкой (например, это должна быть строка внутри двойных кавычек).
gimlichael
Я вижу, как это может быть запутано, предложение могло бы быть немного более кратким, начиная со следующего: «Последовательность из нуля или более символов Юникода…». Я полагаю, что автор, возможно, добавил это для акцента. Я изложил это так, чтобы было легче увидеть некоторые ключевые моменты. Несмотря на запоздалый ответ, я надеюсь, что это добавит ясности в случае необходимости.
J. Морено