[java] Jackson과 매핑 할 때 기본값을 null 필드로 설정

Jackson을 사용하여 일부 JSON 개체를 Java 개체에 매핑하려고합니다. JSON 객체의 일부 필드는 필수이며 (로 표시 할 수 있음 @NotNull) 일부는 선택 사항입니다.

Jackson과의 매핑 후 JSON 개체에 설정되지 않은 모든 필드는 Java에서 null 값을 갖습니다. @NotNullnull 인 경우 Jackson에게 Java 클래스 멤버에 기본값을 설정하도록 지시 할 수 있는 유사한 주석 이 있습니까?

편집 : 질문을 더 명확하게하기 위해 몇 가지 코드 예제가 있습니다.

Java 객체 :

class JavaObject {
    @NotNull
    public String notNullMember;

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

JSON 객체는 다음 중 하나 일 수 있습니다.

{
    "notNullMember" : "notNull"
}

또는:

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

@DefaultValue주석 그냥 내가 요구하고 무엇을 보여주는 것입니다. 실제 주석이 아닙니다. json으로 개체가 첫 번째 예에서와 같이 있으면 난의 값이 원하는 optionalMember일을 "Value"하지 null. 그런 일을하는 주석이 있습니까?



답변

기본값을 설정하는 주석이 없습니다.
Java 클래스 수준에서만 기본값을 설정할 수 있습니다.

public class JavaObject
{
    public String notNullMember;

    public String optionalMember = "Value";
}


답변

제안 된 솔루션 중 하나만 명시 적으로 설정된 default-value시기를 유지합니다 some-value:null(POJO 가독성이 손실되고 어색함).

유지 default-value하고 절대 설정하지 않는 방법은 다음과 같습니다.null

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

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


답변

고유 한 JsonDeserializer를 만들고 해당 속성에 주석을 달 수 있습니다. @JsonDeserialize(as = DefaultZero.class)

예 : BigDecimal을 기본값으로 0으로 구성하려면 다음을 수행하십시오.

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;
 }


답변

해결책은 기본 생성자 내부의 속성 값을 설정하는 것 같습니다. 따라서이 경우 Java 클래스는 다음과 같습니다.

class JavaObject {

    public JavaObject() {

        optionalMember = "Value";
    }

    @NotNull
    public String notNullMember;

    public String optionalMember;
}

Jackson과의 매핑 후 optionalMemberJSON에서이 누락 된 경우 Java 클래스의 값은 "Value".

그러나 주석이 있고 기본 생성자가없는 솔루션이 있는지 여전히 알고 싶습니다.


답변

구성원을 비공개로 만들고 setter / getter 쌍을 추가합니다. setter에서 null이면 대신 기본값을 설정하십시오. 또한 내부 값이 null 일 때 기본값을 반환하는 getter를 사용하여 스 니펫을 표시했습니다.

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;
}


답변

비슷한 문제가 있었지만 제 경우에는 기본값이 데이터베이스에있었습니다. 다음은 그에 대한 해결책입니다.

 @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;
 }

그런 다음 필드 / 객체가 null 인 경우 json을 역 직렬화하고 기본값을 설정 SomeDtoJsonDeserializer하는 ObjectMapper데 사용 됩니다.


답변

이미 많은 좋은 제안이 있지만 여기에 하나 더 있습니다. @JsonDeserialize를 사용하여 Jackson이 post-deserialization을 호출하는 임의의 “sanitizer”를 수행 할 수 있습니다.

@JsonDeserialize(converter=Message1._Sanitizer.class)
public class Message1 extends MessageBase
{
    public String string1 = "";
    public int integer1;

    public static class _Sanitizer extends StdConverter<Message1,Message1> {
        @Override
        public Message1 convert(Message1 message) {
            if (message.string1 == null) message.string1 = "";
            return message;
        }
    }
}