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

jvlzgdj9  于 2022-12-24  发布在  其他
关注(0)|答案(4)|浏览(311)

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

public class Entity {

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

}

如果请求包含空值作为请求属性:

{
  "homes": null
}

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

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.在反序列化过程中,是否有Jackson属性将null更改为空集合?
1.如果第一点没有,我需要写反序列化器吗?如果是,我可以写泛型吗?

rhfm7lfc

rhfm7lfc1#

从Jackson2.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();

我还没有能够尝试这个特性,所以这是基于feature discussion和对unit tests.YMMV的检查。

mo49yndu

mo49yndu2#

我也找不到Jackson属性或注解,所以我不得不对第一个问题回答no,但是我推荐一个简单的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关联起来。

vnzz0bqm

vnzz0bqm3#

对我起作用的是简单地删除setter并使属性成为final。Jackson2随后将使用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

wrrgggsh

wrrgggsh4#

我认为在我的案例中最干净的解决方案在两种情况下都能按预期工作(反序列化后得到空列表而不是null):
1.属性在json(请求)中被省略
1.属性在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)列表需要该解决方案

相关问题