我正在尝试创建一个POJO作为模板来反映传入的JSON。
public class Item {
@JsonProperty("special")
@NotNull
private Boolean special;
@JsonProperty("specialCriteria")
private SpecialCriteria specialCriteria;
}
如果special为true并且JSON中没有提供specialCriteria参数,我想用IllegalArgumentException
使请求无效。
我尝试使用以下@JsonSetter
进行操作,但在我发出JSON请求时收到了HTTP 200
,其中的特殊字符为true,不包含specialCriteria。
@JsonSetter("specialCriteria")
public void setSpecialCriteria(@JsonProperty("specialCriteria") SpecialCriteria specialCriteria) {
if(this.special == false)
specialCriteria = null;
if(this.special == true && specialCriteria != null)
this.specialCriteria = specialCriteria;
else
throw new IllegalArgumentException("Invalid JSON. Please provide Special Criteria.");
}
我还尝试了以下方法:
public void setSpecialCriteria(@JsonProperty("specialCriteria") SpecialCriteria specialCriteria, @JsonProperty("special") Boolean special) {
我如何告诉杰克逊在创建pojo时设置这些限制?
跟进:如果我想对SpecialCriteria类中的参数添加其他限制,那么在给定的解决方案中仍会坚持使用@Valid
吗?
答案 0 :(得分:2)
您的方法存在两个重要问题:
1)您在特定设置器中进行验证的方式不一致,因为您不知道在反序列化过程中(JSON到Java Object),Jackson将按哪些顺序设置字段。因此,字段可能为null
,因为它尚未初始化。 因此验证可能不一致。
2)Jackson进行了优化,只有在反序列化过程中,只要存在该值,就可以使用setter设置字段。它解析JSON并反序列化发现的令牌(不多也不少)。
因此,如果JSON中的值为空,则setter将永远不会在Java对象上被调用。
这些信息不容易发现,但是在这里:
com.fasterxml.jackson.databind.deser.BeanDeserializer
:
@Override
public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
// common case first
if (p.isExpectedStartObjectToken()) {
if (_vanillaProcessing) {
return vanillaDeserialize(p, ctxt, p.nextToken());
}
// 23-Sep-2015, tatu: This is wrong at some many levels, but for now... it is
// what it is, including "expected behavior".
p.nextToken();
if (_objectIdReader != null) {
return deserializeWithObjectId(p, ctxt);
}
return deserializeFromObject(p, ctxt);
}
return _deserializeOther(p, ctxt, p.getCurrentToken());
}
此处p.nextToken();
返回下一个令牌以根据收到的JSON反序列化。
主要迭代方法,该方法将使流足够前进以确定 下一个令牌的类型(如果有)。如果没有剩余(流没有 内容,而不是结束前可能的空白),则将为null 返回。
长话短说,您必须使用API或旨在验证模型的方法,而不是尝试在setter内执行验证逻辑,但这不是正确的方法。
一些选项:
1)Bean Validation API。这可能会有所帮助:http://hibernate.org/validator/documentation/getting-started/。
这对字段的注释约束非常有用。
2)对于代码中的结构化验证:根据某些规则的验证,您不能依赖字段的注释约束。
因此,要么创建验证函数,要么可以将逻辑验证包括在类的构造函数中。如果您用@JsonCreator
注释构造函数,则有可能。