我编写了一个自定义序列化程序和自定义反序列化程序来序列化用@Confidential注解标记的属性。
@Data
public class Person {
private String name;
@Confidential
private String address;
}
自订序列化程式会序列化具有下列值的POJO:
{ "name": "John Doe", "address": "Kearney St"}
如下所示:
{"name":"John Doe", "address": {"value":"IjIwMzEwIDU4dGggTG4gTkUi"}}
自定义反序列化器还能够将JSON反序列化回Person POJO fine。
但是,当我将Person POJO中的字段设置为final时,序列化继续工作,但反序列化失败。
@Data
public class Person {
private final String name;
@Confidential
private final String address;
}
下面是BeanSerializerModifier的实现:
@AllArgsConstructor
public class CustomDeserializerModifier extends BeanDeserializerModifier {
private final ObjectMapper objectMapper;
@Override
public BeanDeserializerBuilder updateBuilder(final DeserializationConfig config,
final BeanDescription beanDesc,
final BeanDeserializerBuilder builder) {
Iterator<SettableBeanProperty> beanPropertyIterator = builder.getProperties();
beanPropertyIterator.forEachRemaining(settableBeanProperty -> {
final Confidential annotation = settableBeanProperty.getAnnotation(Confidential.class);
if (encryptedProperty != null) {
JsonDeserializer<Object> current = settableBeanProperty.getValueDeserializer();
final SettableBeanProperty newSettableBeanProperty =
settableBeanProperty.withValueDeserializer(
new CustomDeserializer(annotation, current, objectMapper)
);
builder.addOrReplaceProperty(newSettableBeanProperty, true);
}
});
return builder;
}
}
我发现当Person POJO字段为final时,永远不会调用CustomDeserializer。
以下是错误消息:
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token
at [Source: {"name":"John Doe","address":{"value":"IjIwMzEwIDU4dGggTG4gTkUi"}}; line: 1, column: 30] (through reference chain: com.custom.model.Person["address"])
JacksonMaven可以告诉我为什么当POJO字段为final时,CustomDeserializer没有被调用。
谢谢你,谢谢你
1条答案
按热度按时间9jyewag01#
如前所述,序列化对于可变字段和不可变字段都能很好地工作。反序列化问题只会在使用不可变字段时发生,因为BeanDeserializerModifier在这种情况下不起作用。
在Jackson术语中,不可变字段被命名为创建者属性,这意味着它们是使用创建者初始化的。请参见BeanDeserializerBase#resolve。
为了正确地处理此用例,可以使用自定义的DeserializationContext创建ObjectMapper(ObjectMapper的扩展实现也可以设置与反序列化上下文相关的受保护字段)。
然后,通过重写方法DeserializationContext#handleSecondaryContextualization,可以更改反序列化以使其正常工作。
也许还有其他的可能性,但这一个是工作的罚款与加密。