programing

잭슨 역직렬화기 - null 컬렉션을 비우도록 변경합니다.

stoneblock 2023. 4. 4. 20:52

잭슨 역직렬화기 - null 컬렉션을 비우도록 변경합니다.

수집을 속성으로 포함하는 엔티티가 있습니다.

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

몇 가지 질문이 있습니다.

  1. 역직렬화 중에 null을 빈 컬렉션으로 변경하는 잭슨 속성이 있습니까?
  2. 첫 번째 포인트에 대해 "아니오"인 경우 - 이 포인트에 대해 역직렬화기를 써야 합니까?만약 그렇다면 범용으로 써도 될까요?

Jackson 2.9에서는 특정 속성에 대한 null 처리를 다음과 같이 구성할 수 있습니다.

@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

Jackson 속성이나 주석을 찾을 수 없었습니다.첫 번째 질문에는 '아니오'라고 대답해야겠네요.단, 특별한 디시리얼라이저 대신 심플한 세터를 추천합니다.

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.

저에게 효과가 있었던 것은 단순히 세터를 제거하고 속성을 최종화하는 것이었습니다.그런 다음 getter를 사용하여 목록을 수정합니다.

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

어느 경우든 예상대로 동작하고 있는(탈직렬화 후 늘이 아닌 빈 목록을 취득) 내 경우에서 가장 깨끗한 솔루션이 될 수 있다고 생각합니다.

  1. json(요청)에서 속성이 생략되었습니다.
  2. json(요청)에서 속성이 null로 명시적으로 설정되어 있습니다.

다음과 같습니다.

@Valid // javax.validation
@Schema(required = false) // swagger.v3 
@JsonProperty(required = false, defaultValue = "") // jackson 2.13
private List<@NotEmpty @Size(max = 100) String> actions = new ArrayList<>();

public List<String> getActions() {
    return actions;
}

@JsonSetter(nulls = Nulls.AS_EMPTY)
public void setActions(List<String> actions) {
    this.actions = actions;
}

주의:

  • 속성이 null로 명시적으로 설정된 경우: 사용된 기본 주석
  • 속성 생략 시: 초기화 추가= new ArrayList<>();
  • 예를 들어 Java 검증을 사용하는 경우 이 솔루션은 옵션용으로만 필요합니다.required = false)의 리스트

언급URL : https://stackoverflow.com/questions/32398885/jackson-deserializer-change-null-collection-to-empty-one