#java #conditional #jackson #deserialization #geojson
#java #условные операторы #джексон #десериализация #geojson
Вопрос:
Мне нужно десериализовать объект GeoJSON JSON с помощью библиотеки Jackson. В этом объекте json есть места, где это применимо:
Если существует
"type" : "name"
чем следующий объект json одного типа. Допустим, например:
"properties": {
"name": "urn:ogc:def:crs:OGC:1.3:CRS84"
}
С другой стороны, если существует
"type": "link"
чем следующий объект json другого типа. Допустим, например:
"properties": {
"href": "http://example.com/crs/42",
"type": "proj4"
}
Теперь у меня есть PropertiesPOJO, который содержит:
private String name;
private String href;
private String type;
Текущее решение требует проверки типа объекта, чтобы мы знали, какие части PropertiesPOJO мы хотим рассмотреть.Это не очень хорошая практика. Я бы предпочел сделать это с помощью пользовательского десериализатора, который десериализует непосредственно в NamePropertiesPOJO или LinkPropertiesPOJO. Одна из идей, которая у меня возникла, — разместить
@JsonDeserialize(using=PropertiesDeserializer.class)
@JsonProperty("properties")
NamePropertiesPOJO namePropertiesPOJO = null;
@JsonDeserialize(using=PropertiesDeserializer.class)
@JsonProperty("properties")
LinkPropertiesPOJO linkPropertiesPOJO = null;
Но я получаю
Произошло исключение JsonMappingException: несколько полей, представляющих свойство «properties»:
Итак, есть ли какой-либо другой способ, которым я могу сделать это более OO, используя аннотации jackson?
С уважением,
Деспот
Ответ №1:
Это известно как «Внешний идентификатор типа», и хотя он еще не поддерживается Jackson (в отличие от идентификаторов типов, которые были бы встроены в Object; в данном случае, как одно дополнительное свойство), это то, для чего поддержка должна быть добавлена в будущем, согласно JACKSON-453. Этого не будет в версии 1.8, но, надеюсь, в следующей версии. GeoJSON — это часто повторяющийся вариант использования для этого — хотелось бы, чтобы они выбрали более распространенный механизм, но из-за популярности формата это высокоприоритетная задача для поддержки.
Комментарии:
1. Спасибо за информацию, StaxMan! Это полезно знать. Я также вижу еще один недостаток Jackson (хотя это довольно хорошая библиотека). Он не может понять, как анализировать объект JSON, когда вы предоставляете List.class . Я знаю, что это не входит в обязанности Джексона предвидеть, но это был реальный сценарий (я ожидаю массив JSON), но иногда, когда запрос неверен или если сервер, который мы запрашиваем, не отвечает, мы получаем объект JSON вместо массива JSON. Итак, мне пришлось переопределить защищенный объект readInternal (класс<?> clazz, HttpInputMessage inputMessage), чтобы проверить наличие ‘{‘ . не по теме, но приятно знать
2. Хм. Я не уверен, что понимаю проблему … если вы хотите указать содержимое массива (для которого требуются параметры типа), это можно сделать с помощью TypeReference (например, new TypeReference<Список<Компонент>>() { }). Может быть, вы могли бы объяснить проблему в списке пользователей jackson?
Ответ №2:
Вы должны быть в состоянии сделать это через
class Pojo {
Map<String,String> properties;
...
}
А затем просто прочитайте материал с карты.
Кроме того, когда у вас есть только POJO, который вы показали без аннотаций, Jackson также должен иметь возможность самостоятельно заполнять нужные переменные. И в установщиках вы могли бы установить флаг это тип 1 или тип 2, так что вы можете затем сделать if (pojo.isType1())
Комментарии:
1. Первая часть, которую вы показали здесь, выполнена с помощью @JsonAnySetter, которая еще хуже, чем мой дизайн — она заполнит переменную properties всеми доступными параметрами json… Второй подход, который вы предлагаете, не очень хорош, поскольку он нарушает определение POJO. В POJO должны быть только простые установщики и геттеры. И, кроме того, мне это действительно не нужно, поскольку я могу выполнить if (type.equals(«name») или if (type.equals («link») и иметь ту же функциональность. Хитрость в том, чтобы заставить десериализатор jackson сделать это за нас! Хотя хорошая попытка. Приветствия!
Ответ №3:
Я думаю, простым ответом было бы отсутствие стратегии jackson json условной десериализации.
Приветствую,
Деспот
P.S.: Если кто-нибудь даст мне решение проблемы (кроме «нет») Я бы с радостью перенес проверку ответа на его ответ!