杰克逊反序列化器 - 将空集合更改为空集合

pep*_*uch 18 java json jackson

我有一个包含集合作为属性的实体:

public class Entity {

    @JsonProperty(value="homes")
    @JsonDeserialize(as=HashSet.class, contentAs=HomeImpl.class)
    private Collection<Home> homes = new ArrayList<Home>();

}
Run Code Online (Sandbox Code Playgroud)

如果request包含null作为请求属性:

{
  "homes": null
}
Run Code Online (Sandbox Code Playgroud)

那么homes被设置为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();
  }
}
Run Code Online (Sandbox Code Playgroud)

这么几个问题:

  1. 是否有一些jackson属性在反序列化期间将null更改为空集合?
  2. 如果没有第一点 - 我需要为此编写反序列化器吗?如果是的话,我可以写一般的吗?

Mik*_*dge 21

从Jackson 2.9开始,看起来可以配置特定属性的空值处理@JsonSetter,例如:

@JsonSetter(nulls = Nulls.AS_EMPTY)
public void setStrings(List<String> strings) {
    this.strings = strings;
}
Run Code Online (Sandbox Code Playgroud)

类似的配置也可以全局应用于集合:

ObjectMapper mapper = objectMapperBuilder()
    .changeDefaultNullHandling(n -> n.withContentNulls(Nulls.AS_EMPTY))
    .build();
Run Code Online (Sandbox Code Playgroud)

或按类型:

ObjectMapper mapper = objectMapperBuilder()
    .withConfigOverride(List.class,
        o -> o.setNullHandling(JsonSetter.Value.forContentNulls(Nulls.AS_EMPTY)))
    .build();
Run Code Online (Sandbox Code Playgroud)

我无法尝试使用该功能,因此这是基于功能讨论单元测试的检查.因人而异.

  • 请注意,根据 Javadoc,仅当该值显式设置为 null(而不是从 JSON 中省略)时才有效。`{"homes": null}` 与 `{}`。 (6认同)
  • + @RuslanStelmachenko `forContentNulls` 用于空数组元素,整个空数组需要 `forValueNulls`:`mapper.configOverride(List.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY));` (4认同)
  • 需要明确的是,杰克逊2.9中没有方法`objectMapperBuilder()`。2.10中有`jsonMapperBuilder()`,这只是Jackson测试中的帮助器方法,它只返回`JsonMapper.builder()`,其中`JsonMapper`是2.10中引入的新帮助器类。在2.9中,可以使用ObjectMapper来配置默认值,例如:mapper.setDefaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.AS_EMPTY));或特定类型:mapper.configOverride(List.class).setSetterInfo(JsonSetter .Value.forContentNulls(Nulls.AS_EMPTY));`。 (2认同)
  • @sasynkamil 在字段级别使用 new 关键字初始化它,它不会被 jackson 覆盖 (2认同)

Man*_*dis 9

我也找不到杰克逊的财产或注释.所以我不得不回答第一个问题.但我会推荐一个简单的setter而不是特殊的反序列化器:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是通用的,因为它只使用Home接口而不是HomeImpl.你不需要@JsonProperty杰克逊会联想setHomeshomes.

  • 让我发疯的一件事是:你不能将 `@JsonDeserialize` 和 `@JsonSetter(nulls=Nulls.AS_EMPTY)` 结合起来。您必须实现“JsonDeserializer#getNullValue()”并删除“@JsonSetter” (2认同)