Deserialize JSON to classes

前端 未结 2 1314
抹茶落季
抹茶落季 2021-02-01 07:41

Server returns such part of JSON:

{\"condition\": {
    \"or\": [
        {
            \"and\": [
                {
                    \"operand\": \"a\",
             


        
相关标签:
2条回答
  • 2021-02-01 08:26

    You should use a class, not an interface. Otherwise, Jackson cannot create an instance.

    I believe you also need to create default (aka no-arg) constructors for your POJOs for Jackson to work.

    Also, a good general approach for creating a Jackson mapping is to instantiate a Java instance of your classes and then create the JSON from that, Java -> JSON. This makes it much easier to understand how the mapping is different - going from JSON -> Java is harder to debug.

    0 讨论(0)
  • 2021-02-01 08:41

    I had to accomplish something very similar, here is an excerpt.

    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "@class")
    @JsonSubTypes({
        @JsonSubTypes.Type(value=IMetricCollection.class, name="MetricCollection"),
        @JsonSubTypes.Type(value=IMetricDouble.class, name="MetricDouble"),
        @JsonSubTypes.Type(value=IMetricInteger.class, name="MetricInteger"),
        @JsonSubTypes.Type(value=IMetricPlot.class, name="MetricPlot"),
        @JsonSubTypes.Type(value=IMetricString.class, name="MetricString"),
        @JsonSubTypes.Type(value=IMetricMatrix.class, name="MetricMatrix")
    })
    
    public interface IMetric extends HasViolations<IViolation>, Serializable {
    
        /**
         * Getter for the name of the object.
         * 
         * @return
         */
        public abstract String getName();
    
        /**
         * Set the name of the object.
         * 
         * @param name
         */
        public abstract void setName(String name);
    
        /**
         * Returns true if metric has violations.
         * @return
         */
        public abstract boolean hasMetricViolations();
    }
    

    This may seem kind of counter intuitive for using an interface but I was able to get this all working by telling the interface what concrete class to use. I also have another chunk of code in a separate project that overrides the JsonSubTypes to instantiate it's own type of classes below, if this helps.

    @JsonDeserialize(as=MetricMatrix.class)
    public interface IMetricMatrix<C extends IColumn> extends IMetric {
    
        public static interface IColumn extends IMetricCollection<IMetric> {
        }
    
        public static interface IIntegerColumn extends IColumn {
        }
    
        public static interface IDoubleColumn extends IColumn {
        }
    
        public static interface IStringColumn extends IColumn {
        }
    
    
        public abstract List<C> getValue();
    
        public abstract void setValue(List<C> value);
    
        public abstract void addColumn(C column);
    }
    

    In this class I can parse the same REST message but I am overriding the original projects concrete types and the subtypes for this project make them persistent. Since the type names are the same I can override what interface to use for this object type. Please keep in mind that I am using the @class property but this is completely arbitrary could be @whatever annotation but it would need to match on both sides. This is not using the JsonTypeInfo.Id.Class annotation.

    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "@class")
    @JsonSubTypes({
        @JsonSubTypes.Type(value=IMetricCollectionEntity.class, name="MetricCollection"),
        @JsonSubTypes.Type(value=IMetricDoubleEntity.class, name="MetricDouble"),
        @JsonSubTypes.Type(value=IMetricIntegerEntity.class, name="MetricInteger"),
        @JsonSubTypes.Type(value=IMetricPlotEntityEntity.class, name="MetricPlot"),
        @JsonSubTypes.Type(value=IMetricStringEntity.class, name="MetricString"),
        @JsonSubTypes.Type(value=IMetricMatrixEntity.class, name="MetricMatrix")
    })
    public interface IMetricEntity extends IDatastoreObject, IMetric {
    
        public String getContext();
    
        public List<IViolation> getViolations();
    }
    
    
    
    @JsonDeserialize(as=MetricMatrixEntity.class)
    public interface IMetricMatrixEntity extends IMetricEntity {
    
        public static interface IColumnEntity extends IColumn {
            public String getName();
        }
    
        public static interface IIntegerColumnEntity extends IColumnEntity {
        }
    
        public static interface IDoubleColumnEntity extends IColumnEntity {
        }
    
        public static interface IStringColumnEntity extends IColumnEntity {
        }
    
        public abstract List<IColumnEntity> getValue();
    
        public abstract void setValue(List<IColumnEntity> value);
    
        public abstract void addColumn(IColumnEntity column);
    }
    
    0 讨论(0)
提交回复
热议问题