如何使用Jackson和Spring Boot提供自定义解串器 [英] How to provide a custom deserializer with Jackson and Spring Boot

查看:253
本文介绍了如何使用Jackson和Spring Boot提供自定义解串器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下三个应用程序:

I have the following three applications:

项目1持有

Project 1 holds

  • 业务逻辑(Spring Cloud功能)
  • 接口 IDemoEntity
    • Business logic (Spring Cloud Function)
    • An interface IDemoEntity
    • 项目2

      • 特定于AWS的处理程序
      • IDemoEntity 的一种实现,带有DynamoDB特定的注释
      • 该项目基于Spring Boot
        • AWS-specific handler
        • One implementation of IDemoEntity, with DynamoDB-specific annotations
        • The project is based on Spring Boot
        • 项目3

          • IDemoEntity 的一个实现,带有CosmosDB批注
          • 天蓝色特定的处理程序
            • One implementation of IDemoEntity, with CosmosDB annotation
            • Azure-specific handler
            • 项目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的实现如下所示:

              For project 2, the implementation of IDemoEntity looks like this:

              @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批注.

              For project 3, the implementation of IDemoEntity would look similar to DynamoDemoEntity, but with CosmosDB annotations.

              结构可能看起来有点复杂,但是其构想如下:

              The structure might look a bit complicated, but the idea is the following:

              1. 一次实施业务逻辑和数据模型(在项目1中)(利用Spring Cloud Function)
              2. 仅针对每个平台实施一个包装项目(我从项目2中的AWS Lambda开始,但针对Azure的项目3看起来很相似),以及特定于平台的内容(例如实体实现,需要特定于DB的东西)注释)
              3. 使用项目1作为依赖项编译特定于平台的项目(例如,AWS Lambda的项目2)

              我已经尝试过了,安装程序基本上可以正常工作了. 但是,有一个大问题:

              I've tried it, and the setup works basically. However, there is one big problem:

              调用上面的 StoreFunction 时,Jackson抛出以下异常:

              When calling the StoreFunction above, Jackson throws the following exception:

              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反序列化到哪个实现.

              That makes sense, because Jackson does not know, to which implementation if IDemoEntity it shall deserialize the received JSON.

              现在最简单的方法是将@JsonDeserialize(as = DynamoDemoEntity.class)放置在IDemoEntity上.

              The easiest way now would be to place a @JsonDeserialize(as = DynamoDemoEntity.class) on IDemoEntity.

              但是,这将破坏我的完整结构:项目1将不包含任何信息,它是与哪个平台特定的项目一起编译的.

              However, that would break my complete structure: Project 1 shall have no information, which platform-specific project it is compiled with.

              有什么想法,我如何提供自定义解串器(例如Spring bean),而又不对项目1进行平台特定的修改?

              Any ideas, how I could provide a custom deserializer (e. g. as Spring bean), but without making platform-specific modifications in project 1?

              推荐答案

              首先,您需要创建自定义DynamoDemoEntityDeserializer,如下所示:

              Firstly, you need to create your custom DynamoDemoEntityDeserializer like below:

              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,如下所示:

              Then you can create bean of com.fasterxml.jackson.databind.Module like below:

              @Bean
              public Module dynamoDemoEntityDeserializer() {
                  SimpleModule module = new SimpleModule();
                  module.addDeserializer(IDemoEntity.class, new DynamoDemoEntityDeserializer());
                  return module;
              }
              

              任何类型为com.fasterxml.jackson.databind.Module的bean都会自动注册到自动配置的Jackson2ObjectMapperBuilder中,并应用于它创建的任何ObjectMapper实例.当您向应用程序中添加新功能时,这提供了一种用于贡献自定义模块的全局机制.

              Any beans of type com.fasterxml.jackson.databind.Module are automatically registered with the auto-configured Jackson2ObjectMapperBuilder and are applied to any ObjectMapper instances that it creates. This provides a global mechanism for contributing custom modules when you add new features to your application.

              来源:如何自定义杰克逊对象映射器

              这篇关于如何使用Jackson和Spring Boot提供自定义解串器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆