如何使用@JsonSubTypes与Jackson YAML Mapper进行多态类型处理

时间:2019-04-27 08:41:22

标签: java jackson yaml

我通过https://www.baeldung.com/jackson-annotations发现了@JsonTypeInfo注释,并试图使用它来动态地将给定的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,但是不能由键(例如AWSSNSTopicAWSServerlessFunction,在这种情况下只是碰巧与类型一致,而不必如此)。

因此,我尝试通过@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;
    }
}

但是,当我查看地图时,有一些键为AWSSNSTopicAWSServerlessFunction的条目,但是相应的resourceInstance对象为null

我哪里出错了?还是用这种方法根本无法解决?

0 个答案:

没有答案