【问题标题】:Jackson deserialization ... Unexpected token (END_OBJECT),Jackson 反序列化 ... 意外令牌 (END_OBJECT),
【发布时间】:2011-09-20 01:47:04
【问题描述】:

我正在尝试使用 Jackson 将 JSON 数组反序列化为 Java 集合。这是由我昨晚在Can I instantiate a superclass and have a particular subclass be instantiated based on the parameters supplied 提出的这个问题的答案所激发的。

我得到的错误是(添加换行符以提高可读性):

org.codehaus.jackson.map.JsonMappingException: 
    Unexpected token (END_OBJECT), expected FIELD_NAME: missing property 'type'
    that is to contain type id  (for class sempedia.model.query.QueryValue)
 at [Source: java.io.StringReader@325aef; line: 1, column: 175] 
    (through reference chain: sempedia.model.query.QueryProperty["values"])

我的情况很复杂。我的数组包含对象,这些对象本身包含一个数组值。该数组又包含同样是对象但不一定相同的值(因此是多态性)。

这是一个示例 JSON 字符串:

[
    {
      "id":"74562",
      "uri":"http://dbpedia.org/ontology/family",
      "name":"family",
      "values":[
         {
            "id":"74563",
            "uri":"http://dbpedia.org/resource/Orycteropodidae",
            "name":"Orycteropodidae"
         }
      ],
      "selected":false
    },
    {
      "id":"78564",
      "uri":"http://dbpedia.org/ontology/someNumber",
      "name":"someNumber",
      "values":[
         {
            "lower":"45",
            "upper":"975",
         }
      ],
      "selected":true
    }
]

我想使用这个(下面的)代码或类似的东西来获取一个对象,它是Collection<QueryProperty> 的实例,我称之为queryProperties

ObjectMapper mapper = new ObjectMapper();  
Collection<QueryProperty> queryProperties = 
   queryProperties = mapper.readValue(query, 
      new TypeReference<Collection<QueryProperty>>(){});

我的反序列化类(它们有我没有打印的公共 getter/setter)如下:

public class QueryProperty {    
    int id;
    String uri;
    String name;
    Set<QueryValue> values;
    String selected;
}

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")  
@JsonSubTypes({  
    @Type(value = ResourceQueryValue.class),  
    @Type(value = NumericQueryValue.class)
    })  
public abstract class QueryValue {
    String type;
}

ResourceQueryValue

public class ResourceQueryValue extends QueryValue{
    int id;
    String uri;
    String name;
}

NumericQueryValue 相同的 JSON 不包含此类型的对象。

public class NumericQueryValue extends QueryValue{
    double lower;
    double upper;
}

堆栈跟踪的初始部分:

org.codehaus.jackson.map.JsonMappingException: Unexpected token (END_OBJECT), expected FIELD_NAME: missing property 'type' that is to contain type id  (for class sempedia.model.query.QueryValue)
 at [Source: java.io.StringReader@325aef; line: 1, column: 175] (through reference chain: sempedia.model.query.QueryProperty["values"])
    at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:163)
    at org.codehaus.jackson.map.deser.StdDeserializationContext.wrongTokenException(StdDeserializationContext.java:240)
    at org.codehaus.jackson.map.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:86)
    at org.codehaus.jackson.map.deser.AbstractDeserializer.deserializeWithType(AbstractDeserializer.java:89)

【问题讨论】:

    标签: json collections polymorphism deserialization jackson


    【解决方案1】:

    通常情况下,写出问题可以帮助您找到解决方案。所以我需要做两件事。

    首先,我需要将类型信息添加到 JSON 中——这不是我真正想做的,但我想你需要在某处提供该信息。

    然后我需要将 QueryValue 上的注释编辑为:

    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")  
    @JsonSubTypes({  
        @Type(value = ResourceQueryValue.class, name = "ResourceQueryValue"),  
        @Type(value = NumericQueryValue.class, name= "NumericQueryValue")
        })  
    

    【讨论】:

    • 是的,需要以某种方式添加额外的类型信息。对于它的价值,子类型的默认名称应该是非限定类型名称(这就是你所拥有的)。但为了以防万一,明确表达可能是个好主意。
    • 你是如何添加类型信息的@ankur。我正在尝试使用 angularJS 来做到这一点。非常感谢。
    猜你喜欢
    • 2011-11-22
    • 2017-05-09
    • 1970-01-01
    • 1970-01-01
    • 2017-06-15
    • 2011-10-13
    • 1970-01-01
    • 2013-03-27
    • 2019-12-13
    相关资源
    最近更新 更多