2011-06-22 15 views
13

Estoy intentando deserializar una matriz JSON en una Colección Java utilizando Jackson. Esto motivado por las respuestas a esta pregunta que hice anoche Can I instantiate a superclass and have a particular subclass be instantiated based on the parameters supplied.Deserialización de Jackson ... Token inesperado (END_OBJECT),

El error Soy gettings es (saltos de línea añaden para facilitar la lectura):

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

Mi situación es bastante complicada. Mi matriz contiene objetos que a su vez contienen un valor que es una matriz. Esta matriz a su vez contiene valores que también son objetos pero que no son necesariamente los mismos (por lo tanto, polimorfismo).

Aquí es una cadena de ejemplo 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 
    } 
] 

me gustaría utilizar este (abajo) código o algo similar para obtener un objeto que es una instancia de Collection<QueryProperty> que he llamado queryProperties

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

Mis clases de deserialización (tienen getters/setters públicos los que no tengo la impresión) se enumeran a continuación:

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 la misma JSON no incluye un objeto de este tipo.

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

parte inicial de Seguimiento de la pila:

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) 

Respuesta

15

como sucede a menudo, escribir una pregunta ayuda a ver la solución. Entonces necesito hacer dos cosas.

En primer lugar, necesito agregar la información de tipo en el JSON, que no es lo que realmente quería hacer, pero supongo que debe proporcionar esa información en alguna parte.

Y luego tengo que editar la anotación en QueryValue ser:

@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

Sí, tiene que ser añadido alguna manera una información de tipo adicional. Por lo que vale, el nombre predeterminado para los subtipos debe ser un nombre de tipo no calificado (que es lo que tiene). Pero probablemente sea una buena idea ser explícito, por las dudas. – StaxMan

+2

Cómo agregaste la información de tipo @ankur. Estoy tratando de hacer eso con angularJS. Muchas gracias. –

Cuestiones relacionadas