gpt4 book ai didi

java - 如何使用 Jackson 有条件地(在其他属性上)反序列化属性?

转载 作者:行者123 更新时间:2023-11-30 01:57:02 24 4
gpt4 key购买 nike

我正在尝试创建一个 POJO 作为模板来反射(reflect)传入的 JSON。

public class Item {
@JsonProperty("special")
@NotNull
private Boolean special;

@JsonProperty("specialCriteria")
private SpecialCriteria specialCriteria;
}

如果特殊为 true 并且 JSON 中未提供specialCriteria 参数,我想使用 IllegalArgumentException 使请求无效。

我尝试使用以下@JsonSetter,但当我发出特殊为true且不包含specialCriteria的JSON请求时,收到了接受的HTTP 200

@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) {

如何告诉 Jackson 在创建 pojo 时设置这些限制?

后续:如果我想在 SpecialCriteria 类中添加额外的参数限制,您给定的解决方案是否仍会遵守使用 @Valid

最佳答案

您的方法提出了两个重要问题:

1) 您验证特定 setter 中的方法不一致,因为您不知道 Jackson 在反序列化过程(JSON 到 java 对象)期间将按什么顺序设置字段。因此,字段可能为 null,因为它尚未初始化。 因此验证可能不一致

2) Jackson 经过优化,仅当值存在时才在反序列化期间使用 setter 设置字段。它解析 JSON 并反序列化发现的 token ,不多也不少。

因此,如果 JSON 中的值为空,则永远不会在 Java 对象上调用 setter。
这些信息不容易发现,但就在这里: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返回下一个要反序列化的 token 。

JSONParser.nextToken()定义为:

Main iteration method, which will advance stream enough to determine type of the next token, if any. If none remaining (stream has no content other than possible white space before ending), null will be returned.

<小时/>

长话短说,您必须使用 API 或旨在验证模型的方法,而不是尝试在 setter 内执行验证逻辑,这不是正确的方法。

一些选项:

1) Bean Validation API 。这可能会有所帮助:http://hibernate.org/validator/documentation/getting-started/ .
这对于字段的注释约束非常有用。

2) 对于代码中的结构化验证:根据某些规则进行不同的验证,您不能依赖字段上的注释约束。
因此,要么创建验证函数,要么作为替代方案,您可以在类的构造函数中包含逻辑验证。如果您使用 @JsonCreator 注释构造函数,这是可能的。

关于java - 如何使用 Jackson 有条件地(在其他属性上)反序列化属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54064835/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com