2016-02-16 2 views
2

У меня есть POJO с полем или свойствами, содержащая коллекцию объектов, что-то вроде этого:Джексон: сериализации неинициализированного поля коллекции, как пустой

public class Box { 

    public List<Items> items; 

} 

По умолчанию значения items равно нуль, и Я не хочу инициализировать его пустым списком.

Теперь, если я попытаюсь сериализовать его с Джексоном, я получаю NullPointerException. Есть простой способ заставить Джексона не ломаться на такое значение и сериализовать его как пустую коллекцию: [ ]?

Примечание. Этот класс является просто упрощенным примером. На самом деле в каждой из них есть сотни классов и несколько полей с разными именами, которые иногда устанавливаются в null, иногда где-то в коде, прерывая сериализацию во время выполнения.

+1

В соответствии с этим: https://github.com/FasterXML/jackson-databind/issues/347 нет простого способа. – user3707125

ответ

1

Если вы не хотите, чтобы изменить договор ваш класс POJO, подумайте о возможности определить пользовательский сериализатор/десериализатор Jackson, который расширяется JsonSerializer <T> и JsonDeserializer <T> соответственно. Например .:

public class CountryDeserializer extends JsonDeserializer<CountryCode> { 
    @Override 
    public CountryCode deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException { 
     return CountryCode.getByCode(jp.getText()); 
    } 
} 

, а затем

@JsonDeserialize(using=CountryDeserializer.class) 
private CountryCode country; 

Вы можете проверить, является ли ваше поле является недействительным и действовать соответствующим образом, в обоих направлениях (сериализации/десериализации).

1

Вы считали, что этот класс является JavaBean? В этом случае, вы могли бы дать значение по умолчанию в поглотителе:

public class Box { 
    private List<Items> items; 
    public List<Items> getItems() { 
     if(null == items) { 
      return Collections.emptyList(); 
     } 
     return this.items; 
    } 
    //Setter here 
} 

Такой подход позволил бы предотвратить много проблем, связанных с предположениями Джексона.

Обновление: на основе пояснения ... Вы можете реализовать собственный сериализатор для типа списка (и/или любой другой желаемой настройки). Обратите внимание, что:

public class ListSerializer extends JsonSerializer<List> { 
    @Override 
    public void serialize(List value, JsonGenerator jgen, SerializerProvider provider) throws IOException, 
      JsonProcessingException { 

     if (null == value) { 
      provider.defaultSerializeValue(new ArrayList<Object>(), jgen); 
     } else { 
      provider.defaultSerializeValue(value, jgen); 
     } 
    } 
} 

//Then your code could set the serializer on the object mapper as follows: 
objectMapper.addSerializer(List.class, new ListSerializer()); 

Повторите для всех таких настроек.

Кодекс был вдохновлен этой статье: http://www.baeldung.com/jackson-custom-serialization

+0

Учитывая, что этот класс используется не только Jackson, ваш код имеет плохой дизайн - вызывающий может добавить элемент в возвращаемый массив, и он исчезнет. И если вы измените этот код для хранения 'items' перед возвратом, вы нарушите условие опроса:« Я не хочу инициализировать его пустым списком ». – user3707125

+0

Согласовано. Но мое предположение заключается в том, что класс должен использоваться только для связывания Джексона. Идеальным является просто сделать его действительным javabean. –

+0

@ErnestKiwele Возможно, я упростил вопрос, пожалуйста, см. Примечание, которое я добавил в конце его. –

2

Самый простой способ решить эту проблему является инициализацией списка в конструкторе по умолчанию:

public class Box { 

    private List<Item> items; 

    public Box() { 
     items = new ArrayList<>(); 
    } 

    public List<Item> getItems() { 
     return items; 
    } 

    public setItems(List<Item> items) { 
     this.items = items; 
    } 

    public void addItem(Item item) { 
     items.add(item); 
    } 
} 
+1

Это даже выделено смело в вопросе: «Я не хочу инициализировать его пустым списком». – user3707125

+0

Я заметил, но я все еще думаю, что это лучший способ решить проблему. –

+0

Конечно, это легко, если у вас есть только один класс и одно поле. Не так просто, если у вас есть сотни классов и количество полей с разными именами в каждом, которые иногда устанавливаются как «null» иногда где-то в коде. Может быть, я упростил вопрос ... :) –

Смежные вопросы