15

服务器返回 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<Condition> conditions) {
   }
}

public class And extends GroupOperation { 
   public And(List<Condition> conditions) {
   }
}

public class Or extends GroupOperation { 
   public Or(List<Condition> conditions) {
   }
}

我添加了下一个杰克逊注释,希望能够反序列化上面的 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" : {
    "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. 我想知道是否可以用杰克逊为原始 JSON 编写反序列化

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

4

2 回答 2

18

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

@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在下面实例化它自己的类类型。

@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注释。

@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);
}
于 2013-01-29T14:24:18.273 回答
1

您应该使用类,而不是接口。否则,Jackson 无法创建实例。

我相信您还需要为您的 POJO 创建默认(又名无参数)构造函数,以便杰克逊工作。

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

于 2013-01-28T20:12:31.037 回答