我有以下三个应用程序:
项目1举行
项目二
项目3
项目1的类如下所示:
public interface IDemoEntity { String getName(); void setName(String name); } @Component public class StoreFunction implements Consumer<Message<IDemoEntity>> { @Override public void accept(Message<IDemoEntity> t) { System.out.println("Stored entity " + t.getPayload().getName()); return; } }
对于项目2,IDemoEntity的实现如下所示:
@DynamoDBTable(tableName = "DemoEntity") public class DynamoDemoEntity implements IDemoEntity { private String name; @Override @DynamoDBHashKey public String getName() { return name; } @Override public void setName(String name) { this.name = name; } }
对于项目3项,实施 IDemoEntity 将类似于 DynamoDemoEntity ,但CosmosDB注解。
该结构可能看起来有点复杂,但是其思路如下:
我已经尝试过了,安装程序基本上可以正常工作。但是,存在一个大问题:
当调用上面的 StoreFunction时 ,Jackson抛出以下异常:
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `de.margul.awstutorials.springcloudfunction.logic.IDemoEntity` (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)"{"name": "Detlef"}"; line: 1, column: 1] at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67) at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1452) at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1028) at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserialize(AbstractDeserializer.java:265) at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3004) at de.margul.awstutorials.springcloudfunction.aws.handler.RestSpringBootApiGatewayRequestHandler.deserializeBody(RestSpringBootApiGatewayRequestHandler.java:57) ... 3 more
这是有道理的,因为杰克逊不知道是否IDemoEntity应该反序列化接收到的JSON 到哪个实现。
IDemoEntity
现在最简单的方法是放置@JsonDeserialize(as = DynamoDemoEntity.class)上IDemoEntity。
@JsonDeserialize(as = DynamoDemoEntity.class)
但是,这将破坏我的完整结构:项目1将不包含任何信息,它是与哪个平台特定的项目一起编译的。
有什么想法,我如何提供自定义反序列化器(例如Spring bean),而又不对项目1进行平台特定的修改?
首先,您需要DynamoDemoEntityDeserializer如下创建自定义:
DynamoDemoEntityDeserializer
class DynamoDemoEntityDeserializer extends JsonDeserializer<DynamoDemoEntity> { @Override public DynamoDemoEntity deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { // return DynamoDemoEntity instance; } }
然后,您可以创建com.fasterxml.jackson.databind.Module如下所示的bean :
com.fasterxml.jackson.databind.Module
@Bean public Module dynamoDemoEntityDeserializer() { SimpleModule module = new SimpleModule(); module.addDeserializer(IDemoEntity.class, new DynamoDemoEntityDeserializer()); return module; }
任何类型为com.fasterxml.jackson.databind.Module的bean都会自动注册到自动配置的Jackson2ObjectMapperBuilder中,并应用于它创建的任何ObjectMapper实例。当您向应用程序中添加新功能时,这提供了一种用于贡献自定义模块的全局机制。
来源:如何自定义杰克逊对象映射器