我有一个包含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:
- 是否有一些jackson属性在反序列化期间将null更改为空集合?
- 如果第一点没有-我需要为此编写反序列化器吗?如果是,我可以写通用的吗?
从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会将setHomes
和homes
关联起来。
对我来说有效的方法是删除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
我认为在这两种情况下,最干净的解决方案是按预期工作(反序列化后获得空列表而不是空):
- 属性在json (request) 中被省略
- 属性在json (request) 中被显式设置为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
)列表