Jackson反序列化器-将null集合更改为空集合



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

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

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

{
  "homes": null
}

则homes设置为空。我要做的是将home设置为空列表。我需要为此编写特殊的反序列化器吗?或者有一个用于集合的反序列化器吗?我尝试的是这个反序列化器,但它看起来很丑(它不是通用的,使用实现而不是接口)。

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

So few questions:

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

从Jackson 2.9开始,看起来可以用@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 .

我也找不到Jackson属性或注释。所以我必须对第一个问题说不。但是我建议使用一个简单的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;
    }
}

这是通用的,因为它只使用Home接口而不是HomeImpl。您不需要@JsonProperty,因为Jackson会将setHomeshomes关联起来。

对我来说有效的方法是删除setter并使属性为final。然后Jackson 2将使用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_setter,默认情况下是打开的:https://github.com/FasterXML/jackson-databind/wiki/Mapper-Features

我认为在这两种情况下,最干净的解决方案是按预期工作(反序列化后获得空列表而不是空):

  1. 属性在json (request)
  2. 中被省略
  3. 属性在json (request)
  4. 中被显式设置为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)列表

最新更新