将JSON反序列化为类
服务器返回JSON的这一部分:
Server returns such part of 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"
}
}
]
}
]
}}
我编写了下一个类层次结构:
I wrote next classes hierarchy:
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<Condition> conditions) {
}
}
public class And extends GroupOperation {
public And(List<Condition> conditions) {
}
}
public class Or extends GroupOperation {
public Or(List<Condition> conditions) {
}
}
我添加了下一个jackson注释,希望反序列化上面的JSON:
I've added next jackson annotations in hope to deserialize JSON above:
@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
。
I marked appropriate constructors as @JsonCreator
.
这不适用于表达式
class。
This doesn't work for Expression
class.
如果我修改每个表达式的JSON
对象有名称表达式:
If I modify JSON that every expression
object has the name "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条件时说无法实例化抽象类需要有关类型的更多信息时失败。所以看起来它在更深层次的解析中失去了注释声明。
It fails when trying to parse "not" condition saying that "can't instantiate abstract class need more information about type". So looks like it loses annotations declaration in deeper parsing.
-
我想知道是否可以使用jackson为原始JSON编写反序列化
I wonder if it's possible to write deserialization with jackson for original JSON
为什么第二种方法不适用于不
反序列化
Why second approach doesn't work for Not
deserialization
我必须完成非常相似的事情,这里有一段摘录。
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();
}
这对于使用界面似乎有点直觉但我能够通过告诉接口使用什么具体类来获得这一切。我还在一个单独的项目中有另一块代码,它覆盖了 JsonSubTypes
,以便在下面实例化它自己的类类型,如果这有帮助的话。
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);
}
在这个类中,我可以解析相同的REST消息,但是我要覆盖原始的项目的具体类型和该项目的子类型使它们具有持久性。由于类型名称相同,我可以覆盖用于此对象类型的接口。请记住,我正在使用@class属性,但这完全是任意的可能是@whatever注释,但它需要在两侧匹配。这不是使用 JsonTypeInfo.Id.Class
注释。
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);
}