Пользовательский десериализатор для любого списка в Джексоне

У меня проблема с неправильными объектами в списках. Например, у меня есть модель JSON:

{ "items": [ { "id": 1, "name": "Item1" }, { "id": 2, "name": "Item2" }, { "id": [], "name": "Item3" } ] } 

и два POJO

 data class BadList(val items: List<BadItem>) data class BadItem(val id: Int, val name: String) 

Конечно, когда парсер натыкается на третий элемент, я получаю исключение

 com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.Integer out of START_ARRAY token at [Source: {"items":[{"id":1,"name":"Item1"},{"id":2,"name":"Item2"},{"id":[],"name":"Item3"}]}; line: 1, column: 19] (through reference chain: my.package.BadList["items"]->java.util.ArrayList[2]->my.package.BadItem["id"]) 

Кто знает, как обойти это? Я хочу пропустить этот неправильный элемент.

Вы можете написать собственный deserializer и реализовать в нем десериализационную логику, например:

 class ItemIdDeserialiser extends JsonDeserializer<Integer> { @Override public Integer deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { Object value = p.getCurrentValue(); //Check if it's Integer if(value instanceof Integer){ return (Integer) value; } return null; //Or return first element if it's a non empty list } } 

Как только это будет сделано, вы можете аннотировать поле @JsonDeserialise чтобы дать команду @JsonDeserialise использовать ваш класс, например:

 class Item { @JsonDeserialize(using = ItemIdDeserialiser.class) private Integer id; } 

Обновить

Если вы просто хотите игнорировать поле в сериализации / десериализации, вы можете аннотировать его с помощью @JsonIgnore , например

 class Item { @JsonIgnore private Integer id; } 

Или еще лучше, удалите id из pojo и добавьте @JsonIgnoreProperties в класс, например:

 @JsonIgnoreProperties(ignoreUnknown = true) class Item { } 

Он автоматически игнорирует свойства, присутствующие в json но не найденные в классе.

Вы можете использовать «HidableSerializer» для этого и проверять данные во время сериализации

1. Создайте интерфейс IHidable

Интерфейс имеет метод isHidden, который вызывается во время сериализации

 package ch.hasselba.jackson.test; public interface IHidable { public boolean isHidden(); } 

2. Измените класс BadItem

Добавьте интерфейс и измените setter id . Когда идентификатор свойства десериализуется, он проверяется, является ли он целым. Если нет, элемент отмечен как плохой.

 package ch.hasselba.jackson.test; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties( {"hidden"} ) public class BadItem implements IHidable{ private Integer id; public String name; private boolean isBadItem; public Integer getId(){ return id; } public void setId(Object value){ if( value instanceof Integer ){ this.id = (Integer) value; }else{ this.isBadItem = true; } } public boolean isHidden() { return isBadItem; } } 

3. Создайте HidableSerializer

 package ch.hasselba.jackson.test; import java.io.IOException; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.std.StdSerializer; @SuppressWarnings("serial") public class HidableSerializer<T> extends StdSerializer<T> { private JsonSerializer<T> defaultSerializer; protected HidableSerializer(Class<T> t) { super(t); } public JsonSerializer<T> getDefaultSerializer() { return defaultSerializer; } public void setDefaultSerializer(JsonSerializer<T> defaultSerializer) { this.defaultSerializer = defaultSerializer; } @Override public void serialize(T value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { if( value instanceof IHidable ){ IHidable hidableValue = (IHidable) value; if( hidableValue.isHidden() ) return; } defaultSerializer.serialize(value, jgen, provider); } } 

4. Зарегистрируйте HidableSerializer и все.

 package ch.hasselba.jackson.test; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationConfig; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.BeanSerializerModifier; public class Demo { @SuppressWarnings("serial") public static void main(String[] args) { // register the HidableSerializer ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(Include.NON_EMPTY); mapper.registerModule(new SimpleModule() { @Override public void setupModule(SetupContext context) { super.setupModule(context); context.addBeanSerializerModifier(new BeanSerializerModifier() { @Override public JsonSerializer<?> modifySerializer( SerializationConfig config, BeanDescription desc, JsonSerializer<?> serializer) { if (BadItem.class.isAssignableFrom(desc.getBeanClass())) { HidableSerializer ser = new HidableSerializer(BadItem.class); ser.setDefaultSerializer(serializer); return ser; } return serializer; } }); } }); String content = "{ \"items\": [ { \"id\": 1, \"name\": \"Item1\" }, { \"id\": 2, \"name\": \"Item2\" }, { \"id\":[], \"name\": \"Item3\" } ]}"; // build the Object BadList test = null; try { test = mapper.readValue(content, BadList.class); } catch (Exception e) { e.printStackTrace(); } // and now convert it back to a String String data = null; try { data = mapper.writeValueAsString(test); } catch (Exception e) { e.printStackTrace(); } // print the result System.out.println( data ); } } 

При изменении id "[]" на значение Integer отображается Item, иначе он пуст.

Результат:

 {"items":[{"id":1,"name":"Item1"},{"id":2,"name":"Item2"}]} 
Intereting Posts
Класс Котлина не найден при построении с дженкинсами Как я могу представить отношение многих к многим с Android Room? ThumbnailUtils.createVideoThumbnail сбой, несмотря на допустимый путь к файлу Добавить фрагмент во время выполнения с причинами Kotlin «К сожалению приложение остановилось» Конвертировать приложение Kotlin для Android с помощью Project Astoria Как сопоставить java.util.Optional <Something> с чем-то? в Котлине почему обработчик исключений coroutine удваивает исходное исключение? filterNotNull в списке Kotlin с общим типом Актер Котлин к актерскому общению Есть ли лучший способ декодировать html прямо на Android? Показать фрагмент в виджетах android Как помещать выражение лямбда после параметров на mapTo вызвать юридический синтаксис? TornadoFX как добавить проверку при редактировании TableView Spring Boot: изменить идентификатор заполнителя почему вызов setText () в OnFocusChangeListener очищает текст в представлении?