Java Language
JSON в Java
Поиск…
Вступление
JSON (JavaScript Object Notation) представляет собой легкий, текстовый, независимый от языка формат обмена данными, который легко людям и машинам читать и писать. JSON может представлять два структурированных типа: объекты и массивы. JSON часто используется в приложениях Ajax, конфигурациях, базах данных и веб-службах RESTful. Java API для JSON Processing предоставляет портативные API для анализа, генерации, преобразования и запроса JSON.
замечания
В этом примере основное внимание уделяется разбору и созданию JSON в Java с использованием различных библиотек, таких как библиотека Google Gson , Jackson Object Mapper и другие.
Примеры использования других библиотек можно найти здесь: Как разбирать JSON в Java
Кодирование данных как JSON
Если вам нужно создать JSONObject
и поместить в него данные, рассмотрите следующий пример:
// Create a new javax.json.JSONObject instance.
JSONObject first = new JSONObject();
first.put("foo", "bar");
first.put("temperature", 21.5);
first.put("year", 2016);
// Add a second object.
JSONObject second = new JSONObject();
second.put("Hello", "world");
first.put("message", second);
// Create a new JSONArray with some values
JSONArray someMonths = new JSONArray(new String[] { "January", "February" });
someMonths.put("March");
// Add another month as the fifth element, leaving the 4th element unset.
someMonths.put(4, "May");
// Add the array to our object
object.put("months", someMonths);
// Encode
String json = object.toString();
// An exercise for the reader: Add pretty-printing!
/* {
"foo":"bar",
"temperature":21.5,
"year":2016,
"message":{"Hello":"world"},
"months":["January","February","March",null,"May"]
}
*/
Декодирование данных JSON
Если вам нужно получить данные из JSONObject
, рассмотрите следующий пример:
String json = "{\"foo\":\"bar\",\"temperature\":21.5,\"year\":2016,\"message\":{\"Hello\":\"world\"},\"months\":[\"January\",\"February\",\"March\",null,\"May\"]}";
// Decode the JSON-encoded string
JSONObject object = new JSONObject(json);
// Retrieve some values
String foo = object.getString("foo");
double temperature = object.getDouble("temperature");
int year = object.getInt("year");
// Retrieve another object
JSONObject secondary = object.getJSONObject("message");
String world = secondary.getString("Hello");
// Retrieve an array
JSONArray someMonths = object.getJSONArray("months");
// Get some values from the array
int nMonths = someMonths.length();
String february = someMonths.getString(1);
optXXX vs getXXX
JSONObject
и JSONArray
есть несколько методов, которые очень полезны при работе с возможностью того, что значение, которое вы пытаетесь получить, не существует или имеет другой тип.
JSONObject obj = new JSONObject();
obj.putString("foo", "bar");
// For existing properties of the correct type, there is no difference
obj.getString("foo"); // returns "bar"
obj.optString("foo"); // returns "bar"
obj.optString("foo", "tux"); // returns "bar"
// However, if a value cannot be coerced to the required type, the behavior differs
obj.getInt("foo"); // throws JSONException
obj.optInt("foo"); // returns 0
obj.optInt("foo", 123); // returns 123
// Same if a property does not exist
obj.getString("undefined"); // throws JSONException
obj.optString("undefined"); // returns ""
obj.optString("undefined", "tux"); // returns "tux"
Те же правила применяются к getXXX
/ optXXX
JSONArray
.
Объект для JSON (библиотека Gson)
Допустим, у вас есть класс под названием Person
с просто name
private class Person {
public String name;
public Person(String name) {
this.name = name;
}
}
Код:
Gson g = new Gson();
Person person = new Person("John");
System.out.println(g.toJson(person)); // {"name":"John"}
Конечно, банда Gson должна быть на пути к классу .
JSON To Object (Библиотека Gson)
Допустим, у вас есть класс под названием Person
с просто name
private class Person {
public String name;
public Person(String name) {
this.name = name;
}
}
Код:
Gson gson = new Gson();
String json = "{\"name\": \"John\"}";
Person person = gson.fromJson(json, Person.class);
System.out.println(person.name); //John
У вас должна быть библиотека gson в вашем пути к классам.
Извлечение одного элемента из JSON
String json = "{\"name\": \"John\", \"age\":21}";
JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject();
System.out.println(jsonObject.get("name").getAsString()); //John
System.out.println(jsonObject.get("age").getAsInt()); //21
Использование Mapper объекта Jackson
Модель Pojo
public class Model {
private String firstName;
private String lastName;
private int age;
/* Getters and setters not shown for brevity */
}
Пример: String to Object
Model outputObject = objectMapper.readValue(
"{\"firstName\":\"John\",\"lastName\":\"Doe\",\"age\":23}",
Model.class);
System.out.println(outputObject.getFirstName());
//result: John
Пример: объект для строки
String jsonString = objectMapper.writeValueAsString(inputObject));
//result: {"firstName":"John","lastName":"Doe","age":23}
подробности
Необходима операция импорта:
import com.fasterxml.jackson.databind.ObjectMapper;
Зависимость Maven: jackson-databind
Экземпляр ObjectMapper
//creating one
ObjectMapper objectMapper = new ObjectMapper();
-
ObjectMapper
является поточно - рекомендуется: иметь общий статический экземпляр
Десериализация:
<T> T readValue(String content, Class<T> valueType)
-
valueType
необходимо указать - возврат будет такого типа - Броски
-
IOException
- в случае проблемы ввода-вывода низкого уровня -
JsonParseException
- если базовый ввод содержит недопустимый контент -
JsonMappingException
- если входная структура JSON не соответствует структуре объекта
-
Пример использования (jsonString - входная строка):
Model fromJson = objectMapper.readValue(jsonString, Model.class);
Метод сериализации:
String writeValueAsString (значение объекта)
- Броски
-
JsonProcessingException
в случае ошибки - Примечание: до версии 2.1 предложение бросков включено в IOException; 2.1 удалили его.
-
Итерация JSON
JSONObject
над свойствами JSONObject
JSONObject obj = new JSONObject("{\"isMarried\":\"true\", \"name\":\"Nikita\", \"age\":\"30\"}");
Iterator<String> keys = obj.keys();//all keys: isMarried, name & age
while (keys.hasNext()) { //as long as there is another key
String key = keys.next(); //get next key
Object value = obj.get(key); //get next value by key
System.out.println(key + " : " + value);//print key : value
}
Итерировать значения JSONArray
JSONArray arr = new JSONArray(); //Initialize an empty array
//push (append) some values in:
arr.put("Stack");
arr.put("Over");
arr.put("Flow");
for (int i = 0; i < arr.length(); i++) {//iterate over all values
Object value = arr.get(i); //get value
System.out.println(value); //print each value
}
JSON Builder - методы цепочки
Вы можете использовать цепочку методов при работе с JSONObject
и JSONArray
.
Пример JSONObject
JSONObject obj = new JSONObject();//Initialize an empty JSON object
//Before: {}
obj.put("name","Nikita").put("age","30").put("isMarried","true");
//After: {"name":"Nikita","age":30,"isMarried":true}
JSONArray
JSONArray arr = new JSONArray();//Initialize an empty array
//Before: []
arr.put("Stack").put("Over").put("Flow");
//After: ["Stack","Over","Flow"]
JSONObject.NULL
Если вам нужно добавить свойство с null
значением, вы должны использовать предопределенный статический конечный JSONObject.NULL
а не стандартную Java- null
ссылку.
JSONObject.NULL
- это контрольное значение, используемое для явного определения свойства с пустым значением.
JSONObject obj = new JSONObject();
obj.put("some", JSONObject.NULL); //Creates: {"some":null}
System.out.println(obj.get("some"));//prints: null
Заметка
JSONObject.NULL.equals(null); //returns true
Что является явным нарушением контракта Java.equals()
:
Для любого ненулевого опорного значения х, x.equals (NULL) должен возвращать ложь
JsonArray в список Java (Gson Library)
Вот простой JsonArray, который вы хотели бы преобразовать в Java ArrayList
:
{
"list": [
"Test_String_1",
"Test_String_2"
]
}
Теперь передайте список JsonArray
'следующему методу, который возвращает соответствующий Java ArrayList
:
public ArrayList<String> getListString(String jsonList){
Type listType = new TypeToken<List<String>>() {}.getType();
//make sure the name 'list' matches the name of 'JsonArray' in your 'Json'.
ArrayList<String> list = new Gson().fromJson(jsonList, listType);
return list;
}
Вы должны добавить следующую зависимость maven к вашему файлу POM.xml
:
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.7</version>
</dependency>
Или у вас должен быть jar com.google.code.gson:gson:jar:<version>
в вашем пути к классам.
Уничтожьте коллекцию JSON в коллекции объектов, используя Jackson
Предположим , у вас есть класс POJO Person
public class Person {
public String name;
public Person(String name) {
this.name = name;
}
}
И вы хотите разобрать его в массив JSON или карту объектов Person. Из-за стирания типа вы не можете создавать классы List<Person>
и Map<String, Person>
непосредственно во время выполнения (и, следовательно, использовать их для десериализации JSON) . Чтобы преодолеть это ограничение, Джексон предлагает два подхода - TypeFactory
и TypeReference
.
TypeFactory
Подход, использованный здесь, заключается в использовании фабрики (и ее статической функции полезности) для создания вашего типа для вас. Требуемые параметры - это коллекция, которую вы хотите использовать (список, набор и т. Д.) И класс, который вы хотите сохранить в этой коллекции.
TypeReference
Тип ссылочного подхода кажется более простым, поскольку он экономит вам немного ввода и выглядит более чистым. TypeReference принимает параметр типа, в котором вы передаете желаемый тип List<Person>
. Вы просто создаете экземпляр объекта TypeReference и используете его в качестве контейнера типа.
Теперь давайте посмотрим, как фактически десериализовать JSON в объект Java. Если ваш JSON отформатирован как массив, вы можете десериализовать его как список. Если существует более сложная вложенная структура, вам необходимо десериализовать карту. Мы рассмотрим примеры обоих.
Удаление десериализации массива JSON
String jsonString = "[{\"name\": \"Alice\"}, {\"name\": \"Bob\"}]"
Подход TypeFactory
CollectionType listType =
factory.constructCollectionType(List.class, Person.class);
List<Preson> list = mapper.readValue(jsonString, listType);
Подход типа Type
TypeReference<Person> listType = new TypeReference<List<Person>>() {};
List<Person> list = mapper.readValue(jsonString, listType);
Десериализация карты JSON
String jsonString = "{\"0\": {\"name\": \"Alice\"}, \"1\": {\"name\": \"Bob\"}}"
Подход TypeFactory
CollectionType mapType =
factory.constructMapLikeType(Map.class, String.class, Person.class);
List<Person> list = mapper.readValue(jsonString, mapType);
Подход типа Type
TypeReference<Person> mapType = new TypeReference<Map<String, Person>>() {};
Map<String, Person> list = mapper.readValue(jsonString, mapType);
подробности
Используемая инструкция импорта:
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
Используемые экземпляры:
ObjectMapper mapper = new ObjectMapper();
TypeFactory factory = mapper.getTypeFactory();
Заметка
Хотя подход TypeReference
может выглядеть лучше, он имеет несколько недостатков:
-
TypeReference
должен бытьTypeReference
с использованием анонимного класса - Вы должны предоставить общую экспликацию
Несоблюдение этого может привести к потере аргумента общего типа, что приведет к неудаче десериализации.