簡體   English   中英

傑克遜序列化和預期令牌(END_OBJECT),預期FIELD_NAME:缺少屬性“名稱”

[英]Jackson serialization and nexpected token (END_OBJECT), expected FIELD_NAME: missing property 'name'

我正在嘗試編寫使用Jackson序列化/反序列化對象的代碼。

這些對象本質上是多態的:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "name")
@JsonSubTypes({
    @Type(value = ComparableQuery.class),
    @Type(value = CompositeQuery.class)
})
public abstract class BaseQuery {

    private final Long characteristicId;

...
}

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "name")
public class CompositeQuery extends BaseQuery {

    private final String operator;
    private final BaseQuery[] queries;

    public CompositeQuery(Long characteristicId, Operator operator, BaseQuery... queries) {
        super(characteristicId);
        this.operator = operator.value;
        this.queries = queries;
    }

...
}

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "name")
@JsonSubTypes({
    @Type(value = EqualQuery.class),
    @Type(value = GreaterOrEqualQuery.class),
    @Type(value = GreaterQuery.class),
    @Type(value = LessOrEqualQuery.class),
    @Type(value = LessQuery.class)
})
public abstract class ComparableQuery extends BaseQuery {

    private final Object value;

    private final String comparisonOperator;

...
}

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "name")
public class EqualQuery extends ComparableQuery {

    public EqualQuery(Long characteristicId, Object value) {
        super(characteristicId, value, "=");
    }

}

我用以下代碼創建了Set<BaseQuery>

    Set<BaseQuery> queries = new HashSet<>();

    BaseQuery megapixelCharacteristicQuery = new CompositeQuery(megapixelCharacteristic.getCharacteristicId(), CompositeQuery.Operator.AND, new GreaterOrEqualQuery(megapixelCharacteristic.getCharacteristicId(), 10), new LessOrEqualQuery(megapixelCharacteristic.getCharacteristicId(), 50));
    queries.add(megapixelCharacteristicQuery);

現在,當我嘗試序列化對象時,會收到以下JSON:

[
   {
      "characteristicId":391,
      "operator":"AND",
      "queries":[
         {
            "name":"GreaterOrEqualQuery",
            "characteristicId":391,
            "value":10,
            "comparisonOperator":">="
         },
         {
            "name":"LessOrEqualQuery",
            "characteristicId":391,
            "value":50,
            "comparisonOperator":"<="
         }
      ]
   }
]

但是當我嘗試反序列化JSON文檔時,我收到以下異常:

com.fasterxml.jackson.databind.JsonMappingException: Unexpected token (END_OBJECT), expected FIELD_NAME: missing property 'name' that is to contain type id  (for class com.example.decision.query.characteristic.BaseQuery)
 at [Source: [{"characteristicId":391,"operator":"AND","queries":[{"name":"GreaterOrEqualQuery","characteristicId":391,"value":10,"comparisonOperator":">="},{"name":"LessOrEqualQuery","characteristicId":391,"value":50,"comparisonOperator":"<="}]}]; line: 1, column: 233] (through reference chain: java.util.HashSet[0])
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:261)

由於某種原因,JSON根對象中沒有name字段。

如何解決?

更新

當我嘗試僅序列化例如megapixelCharacteristicQuery對象時,它工作正常:

BaseQuery megapixelCharacteristicQuery = new CompositeQuery(megapixelCharacteristic.getCharacteristicId(), CompositeQuery.Operator.AND, new GreaterOrEqualQuery(megapixelCharacteristic.getCharacteristicId(), 10), new LessOrEqualQuery(megapixelCharacteristic.getCharacteristicId(), 50));

在這種情況下,Jackson形成以下JSON(帶有正確的"name":"CompositeQuery" ):

{
   "name":"CompositeQuery",
   "characteristicId":391,
   "operator":"AND",
   "queries":[
      {
         "name":"GreaterOrEqualQuery",
         "characteristicId":391,
         "value":10,
         "operator":">="
      },
      {
         "name":"LessOrEqualQuery",
         "characteristicId":391,
         "value":50,
         "operator":"<="
      }
   ]
}

但是將megapixelCharacteristicQuery放在HashSet<BaseQuery>內時,序列化/反序列化仍然不起作用。

如何使其與HashSet一起使用?

另外,當我向JsonTypeInfo批注中添加defaultImpl = CompositeQuery.class時,即使使用HashSet ,它也可以開始正常工作,例如:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "name", defaultImpl = CompositeQuery.class)
@JsonSubTypes({
    @Type(value = ComparableQuery.class),
    @Type(value = CompositeQuery.class)
})
public abstract class BaseQuery {
...
}

但這不是我的選擇,因為我不知道在不同情況下應使用哪種類型,因此我仍在尋找一種解決方案,該方法如何在JSON中正確提供name參數。

最后,感謝以下問題中提供的答案, 為什么傑克遜多態序列化在列表中不起作用? 我找到了解決方案:

Set<BaseQuery> queries = new HashSet<BaseQuery>() {
};

做到了。 現在一切都按預期進行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM