Начало работы с пользовательской десериализацией в Джексоне
1. обзор
В этом кратком руководстве будет показано, как использовать Jackson 2 для десериализации JSON с использованиемcustom Deserializer.
Если вы хотите копнуть глубже и изучитьother cool things you can do with the Jackson 2 - переходите кthe main Jackson tutorial.
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.example.jackson.dtos.Item),
not marked as ignorable (3 known properties: "id", "owner", "itemName"])
at [Source: [email protected]; line: 1, column: 43]
(through reference chain: org.example.jackson.dtos.Item["createdBy"])
Мы решим это, выполнивour own deserialization with a custom Deserializer:
public class ItemDeserializer extends StdDeserializer- {
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, мы можем теперьextract the relevant information from it и построить нашу собственную сущностьItem.
Проще говоря, нам нужноregister this custom deserializer и просто десериализовать 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. Пользовательский десериализатор в классе
В качестве альтернативы мы также можемregister the deserializer directly on the class:
@JsonDeserialize(using = ItemDeserializer.class)
public class Item {
...
}
С десериализатором, определенным на уровне класса, нет необходимости регистрировать его вObjectMapper - сопоставитель по умолчанию будет работать нормально:
Item itemWithOwner = new ObjectMapper().readValue(json, Item.class);
Этот тип конфигурации для каждого класса очень полезен в ситуациях, когда у нас может не быть прямого доступа к необработаннымObjectMapper для настройки.
5. Заключение
В этой статье показано, как использовать Jackson 2 вread non-standard JSON input - и как сопоставить этот ввод с любым графом сущностей Java с полным контролем над сопоставлением.
Реализация всех этих примеров и фрагментов кодаcan be found in my github project - это проект на основе Eclipse, поэтому его должно быть легко импортировать и запускать как есть.