将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”条件时说“无法实例化抽象类需要更多关于类型的信息”时失败。 所以看起来它在更深层次的解析中失去了注释声明。
-
我想知道是否可以使用jackson为原始JSON编写反序列化
-
为什么第二种方法不适用于
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更难调试。