2012-03-22 18 views
53

Tengo una clase de Java MyPojo que estoy interesado en deserializar de JSON. He configurado una clase MixIn especial, MyPojoDeMixIn, para ayudarme con la deserialización. MyPojo tiene solo int y String variables de instancia combinadas con getters y setters apropiados. MyPojoDeMixIn se ve algo como esto:Deserializar JSON a ArrayList <POJO> usando Jackson

public abstract class MyPojoDeMixIn { 
    MyPojoDeMixIn(
     @JsonProperty("JsonName1") int prop1, 
     @JsonProperty("JsonName2") int prop2, 
     @JsonProperty("JsonName3") String prop3) {} 
} 

En mi cliente de prueba hago lo siguiente, pero por supuesto que no funciona en tiempo de compilación, porque hay una JsonMappingException relacionada con una coincidencia de tipos.

ObjectMapper m = new ObjectMapper(); 
m.getDeserializationConfig().addMixInAnnotations(MyPojo.class,MyPojoDeMixIn.class); 
try { ArrayList<MyPojo> arrayOfPojo = m.readValue(response, MyPojo.class); } 
catch (Exception e) { System.out.println(e) } 

Soy consciente de que podía aliviar este problema mediante la creación de un objeto "Respuesta" que sólo tiene un ArrayList<MyPojo> en ella, pero entonces tendría que crear estas un tanto inútiles objetos para cada tipo solo quiero volver .

También busqué en línea en JacksonInFiveMinutes pero tuve un tiempo terrible entendiendo las cosas sobre Map<A,B> y cómo se relaciona con mi problema. Si no puede decirlo, soy completamente nuevo en Java y procedo de un entorno Obj-C. Ellos específicamente mencionan:

Además de la unión a POJOs y tipos "simples", no es una variante adicional: la de la unión a contenedores genéricos (mecanografiadas). Este caso requiere un manejo especial debido al denominado Tipo Borrado (utilizado por Java para implementar genéricos en forma un tanto retrocompatible ), que le impide utilizar algo como Collection.class (que no compila).

Así que si desea enlazar los datos en un mapa, necesitará utilizar:

Map<String,User> result = mapper.readValue(src, new TypeReference<Map<String,User>>() { }); 

Como puedo deserializar directamente a ArrayList?

Respuesta

101

Puede deserializar directamente a una lista utilizando el contenedor TypeReference. Un ejemplo de método:

public static <T> T fromJSON(final TypeReference<T> type, 
     final String jsonPacket) { 
    T data = null; 

    try { 
     data = new ObjectMapper().readValue(jsonPacket, type); 
    } catch (Exception e) { 
     // Handle the problem 
    } 
    return data; 
} 

y se usa así:

final String json = ""; 
Set<POJO> properties = fromJSON(new TypeReference<Set<POJO>>() {}, json); 

.

TypeReference Javadoc

+0

Su respuesta parece estar relacionado con la información sobre cómo utilizar el soporte integrado para 'TypeReference' - Simplemente no entiendo cómo hacerlo ... Por favor, vea mi edición anterior por sus instrucciones sobre cómo para usar genéricos –

+0

Bueno, está relacionado. Pero esto es un fragmento del código de trabajo en producción. Olvídese de su mixin, solo use el código que he mostrado (pero reemplace POJO, por supuesto, con el nombre de su clase de bean real). – Perception

+0

Tu código compilado, pero obtengo una excepción de tiempo de ejecución cuando intento imprimir 'arrayList.toString()' sobre una 'NullPointerException'. Supongo que esto podría ser porque mi 'POJO' no se ajusta a las convenciones de nomenclatura correctas para sus propiedades, es decir, todo el problema es que el servicio web devuelve' Prop1Member' y mi objeto tiene 'Prop1'. Esta es la única razón real por la que estoy usando mixins para empezar, así que no tengo que poner las declaraciones para '@ JsonProperty' en mis objetos puros. –

3

También estoy teniendo el mismo problema. Tengo un json que se debe convertir a ArrayList.

Cuenta se ve así.

Account{ 
    Person p ; 
    Related r ; 

} 

Person{ 
    String Name ; 
    Address a ; 
} 

Todas las clases anteriores se han anotado correctamente. He intentado TypeReference>() {} pero no funciona.

Me da Arraylist pero ArrayList tiene unHashMap enlazado que contiene algunos hashmaps enlazados que contienen los valores finales.

Mi código es el siguiente:

public T unmarshal(String responseXML,String c) 
{ 
    ObjectMapper mapper = new ObjectMapper(); 

    AnnotationIntrospector introspector = new JacksonAnnotationIntrospector(); 

    mapper.getDeserializationConfig().withAnnotationIntrospector(introspector); 

    mapper.getSerializationConfig().withAnnotationIntrospector(introspector); 
    try 
    { 
     this.targetclass = (T) mapper.readValue(responseXML, new TypeReference<ArrayList<T>>() {}); 
    } 
    catch (JsonParseException e) 
    { 
     e.printStackTrace(); 
    } 
    catch (JsonMappingException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

    return this.targetclass; 
} 

finalmente resuelto el problema. Soy capaz de convertir la Lista de JSON cadena directamente a ArrayList de la siguiente manera:

JsonMarshallerUnmarshaller<T>{ 

    T targetClass ; 

    public ArrayList<T> unmarshal(String jsonString) 
    { 
     ObjectMapper mapper = new ObjectMapper(); 

     AnnotationIntrospector introspector = new JacksonAnnotationIntrospector(); 

     mapper.getDeserializationConfig().withAnnotationIntrospector(introspector); 

     mapper.getSerializationConfig().withAnnotationIntrospector(introspector); 
     JavaType type = mapper.getTypeFactory(). 
        constructCollectionType(ArrayList.class, targetclass.getClass()) ; 
     try 
     { 
     Class c1 = this.targetclass.getClass() ; 
     Class c2 = this.targetclass1.getClass() ; 
      ArrayList<T> temp = (ArrayList<T>) mapper.readValue(jsonString, type); 
     return temp ; 
     } 
     catch (JsonParseException e) 
     { 
     e.printStackTrace(); 
     } 
     catch (JsonMappingException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

    return null ; 
    } 

} 
48

Otra forma es utilizar una matriz como un tipo, por ejemplo:

ObjectMapper objectMapper = new ObjectMapper(); 
MyPojo[] pojos = objectMapper.readValue(json, MyPojo[].class); 

esta manera se evita todos los problemas con el objeto de texto, y si realmente necesita una lista siempre se puede convertir la matriz a una lista por:

List<MyPojo> pojoList = Arrays.asList(pojos); 

mi humilde opinión, esto es mucho más fácil de leer.

Y para que sea una lista real (que pueden ser modificados, véase limitaciones de Arrays.asList()), entonces haga lo siguiente:

List<MyPojo> mcList = new ArrayList<>(Arrays.asList(pojos)); 
+2

Esta debería ser la respuesta aceptada, simple y mucho más legible. – dic19

+0

De acuerdo^Esto fue mucho más útil – cstaikos

7

Esta variante se parece más sencillo y elegante.

CollectionType typeReference = 
    TypeFactory.defaultInstance().constructCollectionType(List.class, Dto.class); 
List<Dto> resultDto = objectMapper.readValue(content, typeReference); 
Cuestiones relacionadas