«1. Обзор

JSON (нотация объектов JavaScript) — это упрощенный формат обмена данными, и мы чаще всего используем его для связи клиент-сервер. Его легко читать и писать, и он не зависит от языка. Значение JSON может быть другим объектом JSON, массивом, числом, строкой, логическим значением (true/false) или нулевым значением.

В этом руководстве мы увидим, как создавать, обрабатывать и анализировать JSON, используя одну из доступных библиотек обработки JSON — библиотеку JSON-Java, также известную как org.json.

2. Предпосылки

Сначала нам нужно добавить следующую зависимость в наш pom.xml:

<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20180130</version>
</dependency>

Последнюю версию можно найти в центральном репозитории Maven.

Обратите внимание, что этот пакет уже включен в Android SDK, поэтому мы не должны включать его при его использовании.

3. JSON в Java [пакет org.json]

Библиотека JSON-Java, также известная как org.json (не путать с org.json.simple от Google), предоставляет нам классы, которые используются для анализа и управлять JSON в Java.

Кроме того, эта библиотека также может конвертировать между JSON, XML, заголовками HTTP, файлами cookie, списком с разделителями-запятыми или текстом и т. д.

В этом руководстве мы рассмотрим следующие классы:

  1. JSONObject – similar to Java’s native Map-like object, which stores unordered key-value pairs
  2. JSONArray – an ordered sequence of values similar to Java’s native Vector implementation
  3. JSONTokener – a tool that breaks a piece of text into a series of tokens that can be used by JSONObject or JSONArray to parse JSON strings
  4. CDL – a tool that provides methods to convert comma delimited text into a JSONArray and vice versa
  5. Cookie – converts from JSON String to cookies and vice versa
  6. HTTP – used to convert from JSON String to HTTP headers and vice versa
  7. JSONException – a standard exception thrown by this library

4 JSONObject

JSONObject — это неупорядоченная коллекция пар ключ-значение, напоминающая собственные реализации Map в Java.

    Ключи — это уникальные строки, которые не могут быть нулевыми. Значения могут быть любыми: от Boolean, Number, String или JSONArray до даже объекта JSONObject.NULL. JSONObject может быть представлен строкой, заключенной в фигурные скобки, с ключами и значениями, разделенными двоеточием, и парами, разделенными запятой. У него есть несколько конструкторов для создания JSONObject.

Он также поддерживает следующие основные методы:

  1. get(String key) – gets the object associated with the supplied key, throws JSONException if the key is not found
  2. opt(String key) – gets the object associated with the supplied key, null otherwise
  3. put(String key, Object value) – inserts or replaces a key-value pair in current JSONObject.

Метод put() — это перегруженный метод, который принимает ключ типа String и несколько типов в качестве значения.

Полный список методов, поддерживаемых JSONObject, см. в официальной документации.

Давайте теперь обсудим некоторые основные операции, поддерживаемые этим классом.

4.1. Создание JSON непосредственно из JSONObject

JSONObject предоставляет API, аналогичный интерфейсу Map в Java.

Мы можем использовать метод put() и указать ключ и значение в качестве аргумента:

JSONObject jo = new JSONObject();
jo.put("name", "jon doe");
jo.put("age", "22");
jo.put("city", "chicago");

Теперь наш JSONObject будет выглядеть так:

{"city":"chicago","name":"jon doe","age":"22"}

Существует семь различных перегруженных сигнатур JSONObject. Метод put(). Хотя ключ может быть только уникальной, ненулевой строкой, значение может быть любым.

4.2. Создание JSON из карты

Вместо того, чтобы напрямую помещать ключ и значения в JSONObject, мы можем создать пользовательскую карту, а затем передать ее в качестве аргумента конструктору JSONObject.

Этот пример даст те же результаты, что и выше:

Map<String, String> map = new HashMap<>();
map.put("name", "jon doe");
map.put("age", "22");
map.put("city", "chicago");
JSONObject jo = new JSONObject(map);

4.3. Создание JSONObject из строки JSON

Чтобы преобразовать строку JSON в объект JSON, мы можем просто передать строку в конструктор.

Этот пример даст те же результаты, что и выше:

JSONObject jo = new JSONObject(
  "{\"city\":\"chicago\",\"name\":\"jon doe\",\"age\":\"22\"}"
);

Переданный аргумент String должен быть допустимым JSON; в противном случае этот конструктор может вызвать исключение JSONException.

4.4. Сериализация объекта Java в JSON

Один из конструкторов JSONObject принимает POJO в качестве аргумента. В приведенном ниже примере пакет использует геттеры из класса DemoBean и создает для них соответствующий объект JSONObject.

Чтобы получить JSONObject из объекта Java, нам придется использовать класс, который является действительным Java Bean:

DemoBean demo = new DemoBean();
demo.setId(1);
demo.setName("lorem ipsum");
demo.setActive(true);

JSONObject jo = new JSONObject(demo);

А вот JSONObject jo:

{"name":"lorem ipsum","active":true,"id":1}

Хотя у нас есть способ чтобы сериализовать объект Java в строку JSON, невозможно преобразовать его обратно с помощью этой библиотеки. Если нам нужна такая гибкость, мы можем переключиться на другие библиотеки, такие как Jackson.

5. JSONArray

JSONArray — это упорядоченный набор значений, напоминающий нативную реализацию Vector в Java.

    Значения могут быть любыми: от числа, строки, логического значения, JSONArray или JSONObject до даже объекта JSONObject.NULL. Он представлен строкой, заключенной в квадратные скобки, и состоит из набора значений, разделенных запятыми. Как и JSONObject, у него есть конструктор, который принимает исходную строку и анализирует ее для создания JSONArray.

«Вот основные методы класса JSONArray:

  1. get(int index) – returns the value at the specified index (between 0 and total length – 1), otherwise throws a JSONException
  2. opt(int index) – returns the value associated with an index (between 0 and total length – 1). If there’s no value at that index, then a null is returned.
  3. put(Object value) – append an object value to this JSONArray. This method is overloaded and supports a wide range of data types.

Полный список методов, поддерживаемых JSONArray, см. в официальной документации.

5.1. Создание JSONArray

После инициализации объекта JSONArray мы можем просто добавлять и извлекать элементы с помощью методов put() и get():

JSONArray ja = new JSONArray();
ja.put(Boolean.TRUE);
ja.put("lorem ipsum");

JSONObject jo = new JSONObject();
jo.put("name", "jon doe");
jo.put("age", "22");
jo.put("city", "chicago");

ja.put(jo);

Ниже приведено содержимое нашего JSONArray (код отформатирован для ясность):

[
    true,
    "lorem ipsum",
    {
        "city": "chicago",
        "name": "jon doe",
        "age": "22"
    }
]

5.2. Создание JSONArray непосредственно из строки JSON

Как и JSONObject, JSONArray также имеет конструктор, который создает объект Java непосредственно из строки JSON:

JSONArray ja = new JSONArray("[true, \"lorem ipsum\", 215]");

Этот конструктор может вызвать исключение JSONException, если исходная строка не является допустимой. JSON-строка.

5.3. Создание JSONArray непосредственно из коллекции или массива

Конструктор JSONArray также поддерживает объекты коллекции и массива в качестве аргументов.

Мы просто передаем их в качестве аргумента конструктору, и он возвращает объект JSONArray:

List<String> list = new ArrayList<>();
list.add("California");
list.add("Texas");
list.add("Hawaii");
list.add("Alaska");

JSONArray ja = new JSONArray(list);

Теперь наш JSONArray состоит из следующего:

["California","Texas","Hawaii","Alaska"]

6. JSONTokener

JSONTokener принимает исходную строку в качестве входных данных для своего конструктора и извлекает из нее символы и токены. Он используется внутри классами этого пакета (например, JSONObject, JSONArray) для анализа строк JSON.

Может быть не так много ситуаций, когда мы будем напрямую использовать этот класс, поскольку мы можем добиться той же функциональности, используя другие более простые методы (например, string.toCharArray()):

JSONTokener jt = new JSONTokener("lorem");

while(jt.more()) {
    Log.info(jt.next());
}

Теперь мы можем получить доступ к JSONTokener, например итератор, использующий метод more() для проверки наличия оставшихся элементов и метод next() для доступа к следующему элементу.

Вот токены, полученные из предыдущего примера:

l
o
r
e
m

7. CDL

Нам предоставлен класс CDL (список с разделителями-запятыми) для преобразования текста с разделителями-запятыми в JSONArray и наоборот.

7.1. Создание JSONArray непосредственно из текста с разделителями-запятыми

Чтобы создать JSONArray непосредственно из текста с разделителями-запятыми, мы можем использовать статический метод rowToJSONArray(), который принимает JSONTokener:

JSONArray ja = CDL.rowToJSONArray(new JSONTokener("England, USA, Canada"));

Вот из чего состоит наш JSONArray сейчас:

["England","USA","Canada"]

7.2. Создание текста с разделителями-запятыми из JSONArray

Давайте посмотрим, как отменить предыдущий шаг и получить обратно текст с разделителями-запятыми из JSONArray:

JSONArray ja = new JSONArray("[\"England\",\"USA\",\"Canada\"]");
String cdt = CDL.rowToString(ja);

String cdt теперь содержит следующее:

England,USA,Canada

7.3. Создание JSONArray из JSONObjects с использованием текста с разделителями-запятыми

Для создания JSONArray из JSONObjects мы будем использовать текстовую строку, содержащую как заголовки, так и данные, разделенные запятыми.

Мы разделяем разные строки, используя возврат каретки (\\r) или перевод строки (\\n).

Первая строка интерпретируется как список заголовков, а все последующие строки обрабатываются как данные:

String string = "name, city, age \n" +
  "john, chicago, 22 \n" +
  "gary, florida, 35 \n" +
  "sal, vegas, 18";

JSONArray result = CDL.toJSONArray(string);

Результат объекта JSONArray теперь состоит из следующего (вывод отформатирован для ясности): ~ ~~

[
    {
        "name": "john",
        "city": "chicago",
        "age": "22"
    },
    {
        "name": "gary",
        "city": "florida",
        "age": "35"
    },
    {
        "name": "sal",
        "city": "vegas",
        "age": "18"
    }
]

Обратите внимание, что и данные, и заголовок были предоставлены в одной и той же строке. У нас есть альтернативный способ сделать это, где мы можем добиться той же функциональности, предоставив JSONArray, чтобы заголовки и строка с разделителями-запятыми работали как данные.

Опять же, мы разделяем разные строки, используя возврат каретки (\\r) или перевод строки (\\n):

JSONArray ja = new JSONArray();
ja.put("name");
ja.put("city");
ja.put("age");

String string = "john, chicago, 22 \n"
  + "gary, florida, 35 \n"
  + "sal, vegas, 18";

JSONArray result = CDL.toJSONArray(ja, string);

Здесь мы получим содержимое объекта result точно так же, как и раньше.

8. Cookie

Класс Cookie работает с файлами cookie веб-браузера и имеет методы для преобразования файла cookie браузера в JSONObject и наоборот.

Вот основные методы класса Cookie:

  1. toJsonObject(String sourceCookie) – converts a cookie string into a JSONObject
  2. toString(JSONObject jo) – reverse of the previous method, converts a JSONObject into a cookie String

8.1. Преобразование строки cookie в JSONObject

Чтобы преобразовать строку cookie в JSONObject, мы будем использовать статический метод Cookie.toJSONObject():

String cookie = "username=John Doe; expires=Thu, 18 Dec 2013 12:00:00 UTC; path=/";
JSONObject cookieJO = Cookie.toJSONObject(cookie);

8.2. Преобразование JSONObject в строку cookie

Теперь мы преобразуем JSONObject в строку cookie. Это действие, обратное предыдущему шагу:

String cookie = Cookie.toString(cookieJO);

9. HTTP

Класс HTTP содержит статические методы, которые используются для преобразования заголовков HTTP в JSONObject и наоборот.

Этот класс также имеет два основных метода:

  1. toJsonObject(String sourceHttpHeader) – converts a HttpHeader String to JSONObject
  2. toString(JSONObject jo) – converts the supplied JSONObject to String

9.1. Преобразование JSONObject в заголовок HTTP Метод

HTTP.toString() используется для преобразования JSONObject в строку заголовка HTTP:

JSONObject jo = new JSONObject();
jo.put("Method", "POST");
jo.put("Request-URI", "http://www.example.com/");
jo.put("HTTP-Version", "HTTP/1.1");
String httpStr = HTTP.toString(jo);

«

POST "http://www.example.com/" HTTP/1.1

«Вот из чего будет состоять наша строка httpStr:

Обратите внимание, что при преобразовании заголовка HTTP-запроса JSONObject должен содержать ключи «Method», «Request-URI» и «HTTP-Version». А для заголовка ответа объект должен содержать параметры «HTTP-Version», «Status-Code» и «Reason-Phrase».

9.2. Преобразование строки заголовка HTTP обратно в JSONObject

JSONObject obj = HTTP.toJSONObject("POST \"http://www.example.com/\" HTTP/1.1");

Здесь мы преобразуем строку HTTP, полученную на предыдущем шаге, обратно в тот самый JSONObject, который мы создали на этом шаге:

10. JSONException

JSONException стандартное исключение, создаваемое этим пакетом всякий раз, когда возникает какая-либо ошибка.

Используется во всех классах этого пакета. Исключение обычно сопровождается сообщением, в котором указывается, что именно пошло не так.

11. Заключение

В этой статье мы рассмотрели JSON с использованием Java — org.json — и сосредоточились на некоторых основных функциях, доступных здесь.