2011-06-22 7 views
13

Próbuję deserializować macierz JSON do kolekcji Java za pomocą Jacksona. To zmotywowało mnie do odpowiedzi na to pytanie, które zadałem ostatniej nocy Can I instantiate a superclass and have a particular subclass be instantiated based on the parameters supplied.deserializacja Jacksona ... Nieoczekiwany token (END_OBJECT),

Błąd Jestem gettings jest (podziały wiersza dodana dla czytelności):

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"]) 

Moja sytuacja jest dość skomplikowana. Moja tablica zawiera obiekty, które same zawierają wartość, która jest tablicą. Ta tablica z kolei zawiera wartości, które są również obiektami, ale niekoniecznie są takie same (a więc polimorfizm).

Oto ciąg próbka 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 
    } 
] 

Chciałbym to wykorzystać (poniżej) kod lub coś podobnego, aby przedmiot, który jest instancją Collection<QueryProperty> który nazwałem queryProperties

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

Moje klasy do deserializacji (mają publiczne selektory/setery, których nie drukuję) są wymienione poniżej:

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 samego JSON nie obejmuje tego typu obiekt.

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

Początkowa część ślad stosu:

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) 

Odpowiedz

15

Jak to często bywa, wypisywanie pytanie pomaga zobaczyć rozwiązanie. Więc muszę zrobić dwie rzeczy.

Najpierw muszę dodać informacje o typie do JSON - co nie jest tym, co naprawdę chciałem zrobić, ale myślę, że musisz gdzieś podać te informacje.

A potem muszę edytować adnotację na QueryValue być:

@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

Tak, potrzebuje dodatkowe informacje typu należy dodać jakiś sposób. Dla tego, co jest warte, domyślna nazwa dla podtypów powinna być niekwalifikowaną nazwą typu (co jest tym, co masz). Ale na wszelki wypadek to chyba dobry pomysł. – StaxMan

+2

Jak dodać informacje o typie @ankur. Próbuję to zrobić przy pomocy angularJS. Dziękuję bardzo. –