将JSON反序列化为类

服务器返回JSON的这一部分:

{"condition": { "or": [ { "and": [ { "operand": "a", "operator": "==", "value": "true" }, { "not": { "operand": "b", "operator": "==", "value": "true" } } ] }, { "and": [ { "operand": "b", "operator": "==", "value": "true" }, { "not": { "operand": "a", "operator": "==", "value": "true" } } ] } ] }} 

我写了下一个类层次结构:

 public interface Condition {} public class Expression implements Condition { public Expression(String operator, String operand, String value) { } } public class Not implements Condition { public Not(Condition condition) { } } public abstract class GroupOperation implements Condition { public GroupOperation (List conditions) { } } public class And extends GroupOperation { public And(List conditions) { } } public class Or extends GroupOperation { public Or(List conditions) { } } 

我添加了下一个jackson注释,希望将上面的JSON反序列化:

 @JsonTypeInfo(use=Id.NAME, include=As.WRAPPER_OBJECT) @JsonSubTypes({ @JsonSubTypes.Type(value=Not.class, name="not"), @JsonSubTypes.Type(value=And.class, name="and"), @JsonSubTypes.Type(value=Or.class, name="or"), @JsonSubTypes.Type(value=Expression.class, name=""), }) 

我将适当的构造函数标记为@JsonCreator

这不适用于Expression类。


如果我修改JSON,那么每个expression对象都有名称“expression”:

 "expression" : { "operand": "a", "operator": "==", "value": "true" } 

 @JsonTypeInfo(use=Id.NAME, include=As.WRAPPER_OBJECT) @JsonSubTypes({ @JsonSubTypes.Type(value=Not.class, name="not"), @JsonSubTypes.Type(value=And.class, name="and"), @JsonSubTypes.Type(value=Or.class, name="or"), @JsonSubTypes.Type(value=Expression.class, name="expression"), }) 

它在尝试解析“not”条件时说“无法实例化抽象类需要更多关于类型的信息”时失败。 所以看起来它在更深层次的解析中失去了注释声明。


  1. 我想知道是否可以使用jackson为原始JSON编写反序列化

  2. 为什么第二种方法不适用于Not反序列化

我必须完成非常相似的事情,这里有一段摘录。

 @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, 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(); } 

对于使用接口而言,这似乎有点直观,但我能够通过告诉接口使用哪个具体类来实现这一切。 我还在另一个项目中有另一块代码,如果这有帮助,它会覆盖JsonSubTypes以在JsonSubTypes实例化它自己的类类型。

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

在这个类中,我可以解析相同的REST消息,但是我将覆盖原始项目的具体类型,并且此项目的子类型使它们持久化。 由于类型名称相同,我可以覆盖用于此对象类型的接口。 请记住,我正在使用@class属性,但这完全是任意的可能是@whatever注释,但它需要在两侧匹配。 这不是使用JsonTypeInfo.Id.Class注释。

 @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 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 getValue(); public abstract void setValue(List value); public abstract void addColumn(IColumnEntity column); } 

你应该使用一个类,而不是一个接口。 否则,jackson无法创建实例。

我相信你还需要为你的POJO创建默认(也就是无法)构造函数,让Jackson工作。

此外,创建Jackson映射的一个很好的通用方法是实例化类的Java实例,然后从中创建JSON,Java – > JSON。 这使得更容易理解映射是如何不同的 – 从JSON开始 – > Java更难调试。