Подтвердить что ты не робот

Установка значений по умолчанию для нулевых полей при сопоставлении с Jackson

Я пытаюсь сопоставить некоторые объекты JSON с объектами Java с Jackson. Некоторые из полей в объекте JSON являются обязательными (что я могу отметить с помощью @NotNull), а некоторые являются необязательными.

После сопоставления с Jackson все поля, которые не заданы в объекте JSON, будут иметь нулевое значение в Java. Есть ли аналогичная аннотация для @NotNull, которая может сказать Джексону установить значение по умолчанию для члена класса Java, если оно равно null?

Изменить: Чтобы сделать этот вопрос более ясным, приведен пример кода.

Объект Java:

class JavaObject {
    @NotNull
    public String notNullMember;

    @DefaultValue("Value")
    public String optionalMember;
}

Объект JSON может быть:

{
    "notNullMember" : "notNull"
}

или

{
    "notNullMember" : "notNull",
    "optionalMember" : "optional"
}

Аннотации @DefaultValue - это просто показать, что я прошу. Это не настоящая аннотация. Если объект JSON похож в первом примере, я хочу, чтобы значение optionalMember было "Value", а не null. Есть ли аннотация, которая делает такую ​​вещь?

4b9b3361

Ответ 1

Нет аннотации для установки значения по умолчанию.
Вы можете установить значение по умолчанию только на уровне класса java:

public class JavaObject 
{
    public String notNullMember;

    public String optionalMember = "Value";
}

Ответ 2

Только одно предлагаемое решение сохраняет default-value по default-value когда some-value:null был установлен явно (читаемость POJO там потеряна и неуклюжа)

Вот как можно сохранить default-value по default-value и никогда не устанавливать его на null

@JsonProperty("some-value")
public String someValue = "default-value";

@JsonSetter("some-value")
public void setSomeValue(String s) {
    if (s != null) { 
        someValue = s; 
    }
}

Ответ 3

Похоже, решение состоит в том, чтобы установить значение свойств внутри конструктора по умолчанию. Итак, в этом случае класс java:

class JavaObject {

    public JavaObject() {

        optionalMember = "Value";
    }

    @NotNull
    public String notNullMember;

    public String optionalMember;
}

После сопоставления с Jackson, если в JSON отсутствует optionalMember, его значение в классе Java равно "Value".

Однако мне все еще интересно узнать, есть ли решение с аннотациями и без конструктора по умолчанию.

Ответ 4

Сделайте элемент частным и добавьте пару setter/getter. В вашем сеттере, если значение null, вместо этого установите значение по умолчанию. Кроме того, я показал фрагмент с геттером, также возвращающим значение по умолчанию, когда внутреннее значение равно null.

class JavaObject {
    private static final String DEFAULT="Default Value";

    public JavaObject() {
    }

    @NotNull
    private String notNullMember;
    public void setNotNullMember(String value){
            if (value==null) { notNullMember=DEFAULT; return; }
            notNullMember=value;
            return;
    }

    public String getNotNullMember(){
            if (notNullMember==null) { return DEFAULT;}
            return notNullMember;
    }

    public String optionalMember;
}

Ответ 5

Вы можете создать свой собственный JsonDeserializer и аннотировать это свойство с помощью @JsonDeserialize(as = DefaultZero.class)

Например: чтобы настроить BigDecimal по умолчанию на Ноль:

public static class DefaultZero extends JsonDeserializer<BigDecimal> {
    private final JsonDeserializer<BigDecimal> delegate;

    public DefaultZero(JsonDeserializer<BigDecimal> delegate) {
        this.delegate = delegate;
    }

    @Override
    public BigDecimal deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
        return jsonParser.getDecimalValue();
    }

    @Override
    public BigDecimal getNullValue(DeserializationContext ctxt) throws JsonMappingException {
        return BigDecimal.ZERO;
    }
}

И использование:

class Sth {

   @JsonDeserialize(as = DefaultZero.class)
   BigDecimal property;
 }

Ответ 6

У меня была аналогичная проблема, но в моем случае значение по умолчанию было в базе данных. Ниже приведено решение для этого:

 @Configuration
 public class AppConfiguration {
 @Autowired
 private AppConfigDao appConfigDao;

 @Bean
 public Jackson2ObjectMapperBuilder builder() {
   Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder()
       .deserializerByType(SomeDto.class, 
 new SomeDtoJsonDeserializer(appConfigDao.findDefaultValue()));
   return builder;
 }

Затем в SomeDtoJsonDeserializer используйте ObjectMapper для десериализации json и установки значения по умолчанию, если ваше поле/объект имеет значение null.