Джексон-десериализатор - замените нулевую коллекцию на пустой
У меня есть объект, который содержит коллекцию как атрибут:
public class Entity {
@JsonProperty(value="homes")
@JsonDeserialize(as=HashSet.class, contentAs=HomeImpl.class)
private Collection<Home> homes = new ArrayList<Home>();
}
Если запрос содержит null как свойство запроса:
{
"homes": null
}
тогда для домов установлено значение null. То, что я хочу сделать, - это установить дома для пустого списка. Нужно ли мне писать специальный десериализатор для этого или есть ли для коллекций? То, что я пробовал, - это десериализатор, но он выглядит уродливым (он не является общим и использует реализацию вместо интерфейса).
public class NotNullCollectionDeserializer extends JsonDeserializer<Collection<HomeImpl>> {
@Override
public Collection<HomeImpl> deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
return jsonParser.readValueAs(new TypeReference<Collection<HomeImpl>>(){});
}
@Override
public Collection<HomeImpl> getNullValue() {
return Collections.emptyList();
}
}
Так мало вопросов:
- Есть ли какое-то свойство jackson, которое изменяет значение null на пустую коллекцию во время десериализации?
- Если нет для первой точки - мне нужно написать десериализатор для этого? Если да, могу ли я написать общий текст?
Ответы
Ответ 1
Я также не мог найти свойство Джексона или аннотацию для этого. Поэтому я должен ответить на первый вопрос. Но я бы рекомендовал простой сеттер вместо специального десериализатора:
public class Entity {
@JsonDeserialize(contentAs = HomeImpl.class)
private Collection<Home> homes = new ArrayList<>();
public void setHomes(List<Home> homes) {
if (homes != null)
this.homes = homes;
}
}
Это общий, поскольку он использует только интерфейс Home
вместо HomeImpl
. Вам не нужно @JsonProperty
, поскольку Джексон будет ассоциировать setHomes
и homes
.
Ответ 2
Начиная с Jackson 2.9, похоже, что обработка нулевых @JsonSetter
для определенных свойств может быть настроена с помощью @JsonSetter
, например:
@JsonSetter(nulls = Nulls.AS_EMPTY)
public void setStrings(List<String> strings) {
this.strings = strings;
}
Аналогичная конфигурация также может применяться глобально для коллекций:
ObjectMapper mapper = objectMapperBuilder()
.changeDefaultNullHandling(n -> n.withContentNulls(Nulls.AS_EMPTY))
.build();
Или по типу:
ObjectMapper mapper = objectMapperBuilder()
.withConfigOverride(List.class,
o -> o.setNullHandling(JsonSetter.Value.forContentNulls(Nulls.AS_EMPTY)))
.build();
Я не смог опробовать эту функцию, так что это основано на обсуждении функции и проверке модульных тестов. YMMV.
Ответ 3
Что сработало для меня было просто удалить сеттер и сделать атрибут окончательным. jackson 2 будет использовать геттер для изменения списка.
public class Entity {
@JsonProperty(value="homes")
@JsonDeserialize(as=HashSet.class, contentAs=HomeImpl.class)
private final Collection<Home> homes = new ArrayList<Home>();
public List<Home> getHomes() {
return homes;
}
}
Ответственной функцией является USE_GETTERS_AS_SETTERS, которая включена по умолчанию: https://github.com/FasterXML/jackson-databind/wiki/Mapper-Features