在反序列化各种JSON消息时,我想为某种类型的属性提供默认值。简单地指定Class中的值是generally suggested,但是如果必须在许多类中执行此操作,则这很容易出错。您可能会忘记一个并以null
而不是默认值结束。我的目的是将每个属性Optional<T>
设置为Optional.absent
。由于null
正是Optional
试图消除的,因此将其与杰克逊一起使用已被证明令人沮丧。
Jackson的大多数功能允许您自定义反序列化过程,重点关注作为输入的JSON,而不是实例化您要反序列化的Object的过程。我似乎最接近一般解决方案是建立我自己的ValueInstantiator
,但我还有两个问题:
Optional
实例化为absent
,但不会干扰实例化过程的其余部分?ObjectMapper
? 更新:我想澄清一下,我正在寻找一个不涉及修改包含{{1}的每个类的解决方案}&#39;第我反对违反DRY原则。每当我们将Optional
添加到新的或现有的班级时,我或我的同事都不应该考虑做额外的事情。我希望能够说,&#34;将每个Class中的每个可选字段反序列化为预先填充Optional
&#34;,只进行一次,然后完成。
这意味着以下内容:
答案 0 :(得分:2)
特别是对于java.lang.Optional,杰克逊人自己有一个模块:https://github.com/FasterXML/jackson-datatype-jdk8
Guava Optional由https://github.com/FasterXML/jackson-datatype-guava
涵盖它将为null创建一个Optional.absent,但不会为缺少的JSON值创建: - (。
请参阅https://github.com/FasterXML/jackson-databind/issues/618和https://github.com/FasterXML/jackson-datatype-jdk8/issues/2。
因此,您应该像初始化集合一样初始化Optionals。这是一个很好的做法,所以你应该能够强制执行它。
private Optional<Xxx> xxx = Optional.absent();
private List<Yyy> yyys = Lists.newArrayList();
答案 1 :(得分:1)
您可以编写自定义反序列化程序来处理默认值。实际上,您将为要反序列化的对象类型扩展适当的反序列化器,获取反序列化的值,如果它null
只返回适当的默认值。
这是使用字符串快速完成此操作的方法:
public class DefaultStringModule extends SimpleModule {
private static final String NAME = "DefaultStringModule";
private static final String DEFAULT_VALUE = "[DEFAULT]";
public DefaultStringModule() {
super(NAME, ModuleVersion.instance.version());
addDeserializer(String.class, new DefaultStringDeserializer());
}
private static class DefaultStringDeserializer extends StdScalarDeserializer<String> {
public DefaultStringDeserializer() {
super(String.class);
}
public String deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException {
String deserialized = jsonParser.getValueAsString();
// Use a default value instead of null
return deserialized == null ? DEFAULT_VALUE : deserialized;
}
@Override
public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException {
return deserialize(jp, ctxt);
}
}
}
要与ObjectMapper
一起使用,您可以在实例上注册模块:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new DefaultStringModule());
要处理JSON中不存在的字段的默认值,我通常会通过使用构建器类来完成此操作,该构建器类将使用提供的值构造类,并为缺少的字段添加任何默认值。然后,在反序列化的类(例如MyClass
)上,添加@JsonDeserialize(builder = MyClass.Builder.class)
注释以指示Jackson通过构建器类反序列化MyClass
。