2011-06-22 8 views
13

Tôi đang cố gắng deserialize một mảng JSON thành một Bộ sưu tập Java bằng cách sử dụng Jackson. Điều này được thúc đẩy bởi những câu trả lời cho câu hỏi này tôi đã hỏi tối qua Can I instantiate a superclass and have a particular subclass be instantiated based on the parameters supplied.Jackson deserialization ... Mã thông báo không mong muốn (END_OBJECT),

Các lỗi tôi gettings là (ngắt dòng thêm vào cho dễ đọc):

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: [email protected]; line: 1, column: 175] 
    (through reference chain: sempedia.model.query.QueryProperty["values"]) 

tình hình của tôi là khá phức tạp. Mảng của tôi chứa các đối tượng có chứa một giá trị là một mảng. Mảng này lần lượt chứa các giá trị cũng là các đối tượng nhưng không nhất thiết phải giống nhau (do đó đa hình).

Dưới đây là một chuỗi mẫu 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 
    } 
] 

Tôi muốn sử dụng này (dưới đây) mã hoặc một cái gì đó tương tự để có được một đối tượng là một thể hiện của Collection<QueryProperty> mà tôi đã gọi queryProperties

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

Các lớp học của tôi cho việc deserialization (họ có getters/setters công cộng mà tôi không in) được liệt kê dưới đây:

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 cùng JSON không bao gồm một đối tượng thuộc loại này.

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

phần ban đầu của stack trace:

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: [email protected]; 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) 

Trả lời

15

Như thường xảy ra, viết ra một câu hỏi giúp bạn xem các giải pháp. Vì vậy, tôi cần phải làm hai việc.

Trước hết tôi cần thêm thông tin loại vào JSON - đó không phải là những gì tôi thực sự muốn làm, nhưng tôi đoán bạn cần cung cấp thông tin đó ở đâu đó.

Và sau đó tôi cần phải chỉnh sửa chú thích trên QueryValue là:

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

Vâng, một loại thông tin thêm cần được bổ sung một cách nào đó. Đối với những gì nó có giá trị, tên mặc định cho các loại phụ phải là tên loại không đủ điều kiện (đó là những gì bạn có). Nhưng nó có lẽ là ý tưởng tốt để được rõ ràng, chỉ trong trường hợp. – StaxMan

+2

Bạn đã thêm thông tin loại @ankur như thế nào. Tôi đang cố gắng làm điều đó với angularJS. Cảm ơn bạn rất nhiều. –