Comment fournir un désérialiseur personnalisé avec Jackson et Spring Boot

Margul:

Je les trois applications suivantes:

Projet 1 détient

  • La logique métier (fonction Cloud Spring)
  • Une interface IDemoEntity

projet 2

  • gestionnaire AWS-spécifique
  • Une mise en œuvre de IDemoEntity , avec des annotations spécifiques DynamoDB
  • Le projet est basé sur Spring Boot

projet 3

  • Une mise en œuvre de IDemoEntity , avec l' annotation CosmosDB
  • Azure spécifique gestionnaire

Les classes de projet 1 ressemblent à ceci:

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;
    }
}

Pour le projet 2, la mise en œuvre de IDemoEntity ressemble à ceci:

@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;
    }    
}

Pour le projet 3, la mise en œuvre de IDemoEntity ressemblerait à DynamoDemoEntity , mais avec annotations CosmosDB.

La structure peut sembler un peu compliqué, mais l'idée est la suivante:

  1. Mettre en œuvre la logique métier et le modèle de données une seule fois (dans le projet 1) (tirant parti de fonction Cloud Spring)
  2. Mettre en œuvre tout un projet d'emballage pour chaque plate-forme (je commence avec AWS Lambda dans le projet 2, mais le projet 3 pour Azure serait similaire), ainsi que des choses spécifiques de la plate-forme (comme la mise en œuvre de l'entité, qui a besoin d'annotations DB spécifiques)
  3. Compiler le projet spécifique à la plate-forme (par exemple 2 pour projeter AWS Lambda) avec le projet comme une dépendance

Je l'ai essayé, et la configuration fonctionne essentiellement. Cependant, il y a un gros problème:

Lorsque vous appelez le StoreFunction ci - dessus, Jackson lance l'exception suivante:

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

Cela a du sens, parce que Jackson ne sait pas, auquel la mise en œuvre si IDemoEntityelle désérialiser le JSON reçu.

La façon la plus facile maintenant serait de placer un @JsonDeserialize(as = DynamoDemoEntity.class)sur IDemoEntity.

Toutefois, cela briserait ma structure complète: Projet 1 aura aucune information, quel projet spécifique à la plate-forme, il est compilé avec.

Toutes les idées, la façon dont je pourrais fournir un sérialiseur personnalisé (par exemple le haricot printemps), mais sans modifications spécifiques de la plate-forme dans le projet 1?

Sukhpal Singh:

, Vous devez d' abord créer votre commande DynamoDemoEntityDeserializercomme ci - dessous:

class DynamoDemoEntityDeserializer extends JsonDeserializer<DynamoDemoEntity> {
    @Override
    public DynamoDemoEntity deserialize(JsonParser p, DeserializationContext ctxt)
                throws IOException, JsonProcessingException {
       // return DynamoDemoEntity instance;
    }
}

Ensuite , vous pouvez créer des haricots com.fasterxml.jackson.databind.Modulecomme ci - dessous:

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

Tous les haricots de type com.fasterxml.jackson.databind.Module sont automatiquement enregistrés avec le Jackson2ObjectMapperBuilder configuré automatiquement et sont appliqués à toutes les instances ObjectMapper qu'il crée. Cela fournit un mécanisme global pour contribuer modules personnalisés lorsque vous ajoutez de nouvelles fonctionnalités à votre application.

Source: howto-customize-la-jackson-objectmapper

Je suppose que tu aimes

Origine http://43.154.161.224:23101/article/api/json?id=222299&siteId=1
conseillé
Classement