如何用Jackson序列化AbstractUnit字段?

时间:2018-06-07 02:04:01

标签: java jackson units-of-measurement jackson-databind

如果Class0属性具有静态类型unit

,我可以成功序列化Unit
public class Class0 {
    private Unit<?> unit;
    [0-arg constructor, getter and setter]
}

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new UnitJacksonModule());
Class0 value = new Class0((AbstractUnit) SQUARE_METRE);
String json = objectMapper.writeValueAsString(value);
Class0 deserialized = objectMapper.readValue(json, Class0.class);
assertEquals(value, deserialized);

但是,我希望unit拥有静态类型tec.uom.se.AbstractUnit,因为它是Serializable,这对JPA @Basic持久性很重要,但由于

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `tec.uom.se.AbstractUnit` (no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
 at [Source: (String)"{"unit":"m2"}"; line: 1, column: 9] (through reference chain: de.richtercloud.jackson.unit.serialization.Class0["unit"])
    at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
    at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1451)
    at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1027)
    at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserialize(AbstractDeserializer.java:265)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2992)
    at de.richtercloud.jackson.unit.serialization.TheTest.testSerializationAndDeserialization(TheTest.java:30)
[some more irrelevant lines]

使用ObjectMapper.enableDefaultTyping启用默认输入会导致序列化在因{/ 1}}从Unit更改为AbstractUnit之前已失败

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot find a (Map) Key deserializer for type [simple type, class javax.measure.Unit<java.lang.Object>]
 at [Source: (String)"{"unit":["tec.uom.se.unit.ProductUnit","m2"]}"; line: 1, column: 40] (through reference chain: de.richtercloud.jackson.unit.serialization.Class0["unit"])
    at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
    at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1451)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._handleUnknownKeyDeserializer(DeserializerCache.java:599)
    at com.fasterxml.jackson.databind.deser.DeserializerCache.findKeyDeserializer(DeserializerCache.java:168)
    at com.fasterxml.jackson.databind.DeserializationContext.findKeyDeserializer(DeserializationContext.java:500)
    at com.fasterxml.jackson.databind.deser.std.MapDeserializer.createContextual(MapDeserializer.java:248)
    at com.fasterxml.jackson.databind.DeserializationContext.handlePrimaryContextualization(DeserializationContext.java:651)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.resolve(BeanDeserializerBase.java:484)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:293)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
    at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
    at com.fasterxml.jackson.databind.DeserializationContext.findContextualValueDeserializer(DeserializationContext.java:444)
    at com.fasterxml.jackson.databind.jsontype.impl.TypeDeserializerBase._findDeserializer(TypeDeserializerBase.java:194)
    at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._deserialize(AsArrayTypeDeserializer.java:97)
    at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer.deserializeTypedFromScalar(AsArrayTypeDeserializer.java:66)
    at com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer.deserializeWithType(StdScalarDeserializer.java:26)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2992)
    at de.richtercloud.jackson.unit.serialization.TheTest.testSerializationAndDeserialization(TheTest.java:30)
[some more irrelevant lines]

我显然不能注释Unit声明它是序列化支持的子类型,因为它是作为依赖项传递的第三方接口。

使用

@JsonSerialize(as = Unit.class)
@JsonDeserialize(as = Unit.class)
private AbstractUnit<?> unit;

原因

com.fasterxml.jackson.databind.JsonMappingException: Failed to narrow type [simple type, class tec.uom.se.AbstractUnit<java.lang.Object>] with annotation (value javax.measure.Unit), from 'setUnit': Class javax.measure.Unit not subtype of [simple type, class tec.uom.se.AbstractUnit<java.lang.Object>]
    at com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector.refineDeserializationType(JacksonAnnotationIntrospector.java:1130)
    at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.resolveMemberAndTypeAnnotations(BasicDeserializerFactory.java:2082)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.constructSettableProperty(BeanDeserializerFactory.java:791)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.addBeanProps(BeanDeserializerFactory.java:514)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:227)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:137)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:411)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:349)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:264)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
    at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
    at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:477)
    at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:4178)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3997)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2992)
    at de.richtercloud.jackson.unit.serialization.TheTest.testSerializationAndDeserialization(TheTest.java:30)

我知道几乎所有的Unit都是AbstractUnit,因此Serializable,但是我想要正确地做到这一点。我正在寻找一个纯粹的JPA解决方案,即不是特定于实现的解决方案,比如在Hibernate运行时检查的接口子类型的规范。

我正在使用

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.4</version>
</dependency>
<dependency>
    <groupId>tec.uom</groupId>
    <artifactId>uom-se</artifactId>
    <version>1.0.8</version>
</dependency>
<dependency>
    <groupId>com.opower.unitsofmeasure</groupId>
    <artifactId>jackson-module-unitsofmeasure</artifactId>
    <version>1.3.5-SNAPSHOT</version>
</dependency>

0 个答案:

没有答案