Как использовать @JsonSubTypes для обработки полиморфных типов с помощью Jackson YAML Mapper - PullRequest
0 голосов
/ 27 апреля 2019

Я обнаружил аннотацию @JsonTypeInfo с помощью https://www.baeldung.com/jackson-annotations и попытался использовать ее для динамического разбора заданного YAML-файла на различные POJO. YAML может выглядеть так:

AWSTemplateFormatVersion: '2010-09-09'
Resources:
  AWSSNSTopic:
    Properties:
      Subscription:
        Endpoint: someEnpointInfo
        Protocol: email
    ResourceName: HelloWorldTopic
    Type: AWS::SNS::Topic
  AWSServerlessFunction:
    Properties:
      Attributes: SomeString
    ResourceName: HelloWorldFunction
    Type: AWS::Serverless::Function
Transform: AWS::Serverless-2016-10-31

Я хочу динамически анализировать Resources, поскольку свойства объектов внутри Resources зависят от свойства Type, но не могут зависеть от ключей (таких как AWSSNSTopic или * 1011). * которые в данном случае соответствуют только типу, но не обязаны).

Поэтому я попытался как-то решить эту проблему с помощью @JsonSubTypes, чтобы отследить свойство Type и решить, какой тип POJO будет отображаться. Это может выглядеть следующим образом:

public class AWSLambdaResource {

    @JsonProperty("AWSTemplateFormatVersion")
    private String AWSTemplateFormatVersion;

    @JsonProperty("Transform")
    private String Transform;

    @JsonProperty("Resources")
    private Map<String, Ressource> Resources;

    public String getAWSTemplateFormatVersion() {
        return AWSTemplateFormatVersion;
    }

    public void setAWSTemplateFormatVersion(String AWSTemplateFormatVersion) {
        this.AWSTemplateFormatVersion = AWSTemplateFormatVersion;
    }

    public String getTransform() {
        return Transform;
    }

    public void setTransform(String Transform) {
        this.Transform = Transform;
    }

    public Map<String, Ressource> getResources() {
        return Resources;
    }

    public void setResources(Map<String, Ressource> resources) {
        Resources = resources;
    }
}
public class Ressource {

    public ResourceInstance resourceInstance;

    @JsonTypeInfo(
            use = JsonTypeInfo.Id.NAME,
            include = JsonTypeInfo.As.PROPERTY,
            property = "Type")
    @JsonSubTypes({
            @JsonSubTypes.Type(value = AWSServerlessFunction.class, name = "AWS::Serverless::Function"),
            @JsonSubTypes.Type(value = AWSSNSTopic.class, name = "AWS::SNS::Topic")
    })
    public static class ResourceInstance {

        @JsonProperty("Type")
        public String type;

        @JsonProperty("ResourceName")
        public String resourceName;

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public String getResourceName() {
            return resourceName;
        }

        public void setResourceName(String resourceName) {
            this.resourceName = resourceName;
        }
    }

    @JsonTypeName("AWSServerlessFunction")
    public static class AWSServerlessFunction extends ResourceInstance {

        @JsonProperty("ResourceName")
        private String resourceName;

        @JsonProperty("Properties")
        private Properties properties;

        public static class Properties {

            @JsonProperty("Attributes")
            public String attributes;

            public String getAttributes() {
                return attributes;
            }

            public void setAttributes(String attributes) {
                this.attributes = attributes;
            }
        }

        public String getResourceName() {
            return resourceName;
        }

        public void setResourceName(String resourceName) {
            this.resourceName = resourceName;
        }

        public Properties getProperties() {
            return properties;
        }

        public void setProperties(Properties properties) {
            this.properties = properties;
        }
    }

    @JsonTypeName("AWSSNSTopic")
    public static class AWSSNSTopic extends ResourceInstance {

        @JsonProperty("Subscription")
        public Subscription subscription;

        public static class Subscription {

            @JsonProperty("Endpoint")
            public String endpoint;

            @JsonProperty("Protocol")
            public String protocol;

            public String getEndpoint() {
                return endpoint;
            }

            public void setEndpoint(String endpoint) {
                this.endpoint = endpoint;
            }

            public String getProtocol() {
                return protocol;
            }

            public void setProtocol(String protocol) {
                this.protocol = protocol;
            }
        }

        public Subscription getSubscription() {
            return subscription;
        }

        public void setSubscription(Subscription subscription) {
            this.subscription = subscription;
        }
    }

    public ResourceInstance getResourceInstance() {
        return resourceInstance;
    }

    public void setResourceInstance(ResourceInstance resourceInstance) {
        this.resourceInstance = resourceInstance;
    }
}

Однако, когда я смотрю на карту, появляются записи с ключами AWSSNSTopic и AWSServerlessFunction, но соответствующие resourceInstance объекты null.

Где я ошибся? Или это просто невозможно решить с помощью такого подхода?

...