Перейти к основному содержимому

Начало работы с пользовательской десериализацией в Джексоне

· 3 мин. чтения

Упражнение: Сложение двух чисел

Даны два неотрицательный целых числа в виде непустых связных списков. Их цифры хранятся в обратном порядке. И каждый елемент списка содержить ровно одну цифру. Сложите эти два числа и верните сумму в виде связного списка ...

ANDROMEDA

1. Обзор

В этом кратком руководстве показано, как использовать Jackson 2 для десериализации JSON с помощью пользовательского десериализатора.

Чтобы углубиться в другие интересные вещи, которые мы можем делать с Jackson 2 , перейдите к основному учебнику по Джексону .

2. Стандартная десериализация

Давайте начнем с определения двух объектов и посмотрим, как Джексон будет десериализовать представление JSON в эти объекты без какой-либо настройки:

public class User {
public int id;
public String name;
}
public class Item {
public int id;
public String itemName;
public User owner;
}

Теперь давайте определим представление JSON, которое мы хотим десериализовать:

{
"id": 1,
"itemName": "theItem",
"owner": {
"id": 2,
"name": "theUser"
}
}

И, наконец, давайте разместим этот JSON в Java Entities:

Item itemWithOwner = new ObjectMapper().readValue(json, Item.class);

3. Пользовательский десериализатор на ObjectMapper

В предыдущем примере представление JSON идеально соответствовало сущностям Java.

Далее мы упростим JSON:

{
"id": 1,
"itemName": "theItem",
"createdBy": 2
}

При распаковке этого для одних и тех же объектов по умолчанию это, конечно, не удастся:

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: 
Unrecognized field "createdBy" (class org.foreach.jackson.dtos.Item),
not marked as ignorable (3 known properties: "id", "owner", "itemName"])
at [Source: java.io.StringReader@53c7a917; line: 1, column: 43]
(through reference chain: org.foreach.jackson.dtos.Item["createdBy"])

Мы решим эту проблему, выполнив собственную десериализацию с помощью пользовательского Deserializer :

public class ItemDeserializer extends StdDeserializer<Item> { 

public ItemDeserializer() {
this(null);
}

public ItemDeserializer(Class<?> vc) {
super(vc);
}

@Override
public Item deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
JsonNode node = jp.getCodec().readTree(jp);
int id = (Integer) ((IntNode) node.get("id")).numberValue();
String itemName = node.get("itemName").asText();
int userId = (Integer) ((IntNode) node.get("createdBy")).numberValue();

return new Item(id, itemName, new User(userId, null));
}
}

Как мы видим, десериализатор работает со стандартным представлением JSON Джексона — JsonNode . Как только входной JSON представлен в виде JsonNode , мы можем теперь извлечь из него соответствующую информацию и создать нашу собственную сущность Item .

Проще говоря, нам нужно зарегистрировать этот пользовательский десериализатор и нормально десериализовать JSON:

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(Item.class, new ItemDeserializer());
mapper.registerModule(module);

Item readValue = mapper.readValue(json, Item.class);

4. Пользовательский десериализатор класса

Кроме того, мы также можем зарегистрировать десериализатор непосредственно в классе :

@JsonDeserialize(using = ItemDeserializer.class)
public class Item {
...
}

С десериализатором, определенным на уровне класса, нет необходимости регистрировать его в ObjectMapper — сопоставитель по умолчанию будет работать нормально:

Item itemWithOwner = new ObjectMapper().readValue(json, Item.class);

Этот тип конфигурации для каждого класса очень полезен в ситуациях, когда у нас может не быть прямого доступа к необработанному ObjectMapper для настройки.

5. Вывод

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

Реализацию всех этих примеров и фрагментов кода можно найти на GitHub . Это проект на основе Maven, поэтому его легко импортировать и запускать как есть.