Tengo una clase de Java MyPojo que estoy interesado en la deserialización de JSON. He configurado un especial MixIn clase, MyPojoDeMixIn, para que me ayude con la deserialización. MyPojo sólo ha int y String variables de instancia, combinada con el getters y setters. MyPojoDeMixIn se ve algo como esto:

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 un JsonMappingException relacionada con un tipo de desajuste.

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 yo podría aliviar este problema mediante la creación de una «Respuesta» objeto que tiene sólo un ArrayList<MyPojo> en ella, pero entonces tendría que crear esta clase de objetos inútiles para cada tipo de quiero volver.

También busqué en línea en JacksonInFiveMinutes pero había un momento terrible la comprensión de las cosas sobre Map<A,B> y cómo se relaciona con mi tema. Si usted no puede decir, soy totalmente nuevo en Java y venir de un Obj-C de fondo. Especialmente se menciona:

Además de la unión a POJOs y «simple» tipos, hay una
variante adicional: la de la unión a los genéricos (escrito) los recipientes.
Este caso requiere un tratamiento especial debido a la llamada Tipo de Borrado
(utilizado por Java para implementar los genéricos en algo compatible
manera), lo que impide el uso de algo como
De la colección.clase (que no compila).

Así que si quieres enlazar datos en un Mapa que se necesita para usar:

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

¿Cómo puedo deserializar directamente a ArrayList?

5 Comentarios

  1. 130

    Puede deserializar directamente a una lista mediante el uso de la TypeReference contenedor. 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

    • Su respuesta parece estar relacionada con su información sobre cómo utilizar el built-in de apoyo para TypeReference – yo no entiendo cómo hacerlo… por Favor ver mi edición anterior para las instrucciones sobre cómo utilizar los medicamentos genéricos.
    • Bueno, es relativa. Pero este es un fragmento de código de trabajo en la producción. Olvídate de tu mixin, sólo tiene que utilizar el código que he demostrado (pero reemplazar POJO, por supuesto, con el nombre de tu clase bean).
    • El código compilado, pero me da un tiempo de ejecución de la excepción al intentar imprimir el arrayList.toString() sobre un NullPointerException. Supongo que esto podría ser porque mi POJO no se ajusta a la derecha de las convenciones de nomenclatura para sus propiedades, esto es, el problema es que el servicio web devuelve Prop1Member y mi objeto ha Prop1. Esta es la única verdadera razón por la que estoy usando mixins para empezar, así que no tengo que poner las declaraciones de @JsonProperty en mis objetos puros.
    • Inspeccione visualmente la matriz para asegurarse de que tienes una lista de al menos. Y si es necesario agregar el mixin espalda, que debe de trabajo junto con el TypeReference para conseguir todo perfectamente deserializa.
    • Sé que el response cadena es sin duda un JSON válido representación de una matriz. Ahora mismo tengo la excepción de tiempo de ejecución: org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "PropertyMember" (Class com.obfuscated.general.Object), not marked as ignorable at [Source: [email protected]; line: 1, column: 30] (through reference chain: com.obfuscated.general.Object["PropertyMember"]) entonces, ¿cómo puedo incorporar a mi mixin? Perdóname si su gruesa pregunta, soy nuevo en Java.
    • Y para ser claros, el código funciona de maravilla cuando agrego el @JsonProperty declaraciones en el objeto en sí, pero me han dicho que este es un indeseable cosa que hacer, y le recetó el mixin solución como el antídoto.
    • no es tan malo como la gente lo hace también. Es difícil alejarse de proveedor de anotaciones específicas de lo que con el estado actual de la normalización (mínimo) en el campo.
    • Cualquiera de los ejemplos de cómo deserializar objetos json en Listas con jackson 2.x api?
    • La respuesta de @DevNG el uso de Matrices.asList para convertir una matriz o de objetos mapeados es mejor que esta
    • Sólo para tu información, he aquí la sintaxis necesaria en Kotlin: objectMapper.readValue<List<POJO>>(fileOrString, object : TypeReference<List<POJO>>() {})
    • Si, como yo, se trató de mover ese tipo de parámetro en el fromJson método, usted podría encontrar rápidamente de que no funciona. Es esto debido al tipo de borrado?

  2. 83

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

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

    De esta manera se evita todos los problemas con el Tipo de objeto, y si usted realmente necesita una lista que puede convertir la matriz en una lista por:

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

    Mi humilde opinión, esto es mucho más legible.

    Y para que esto sea una lista (que puede ser modificada, consulte las limitaciones de Arrays.asList()) a continuación, sólo hacer lo siguiente:

    List<MyPojo> mcList = new ArrayList<>(Arrays.asList(pojos));
    • Esto debe ser aceptado respuesta, simple y mucho más fácil de leer, de hecho.
    • Acordado^ Esta era la forma más útil
    • Elegante, seguro, pero yo soy incapaz de generify porque de MyPojo[].la clase , que no quiero que pase como parámetro.
    • Creo que el uso de TypeFactory como se describe en la siguiente respuesta: stackoverflow.com/a/42458104/91497 es la de Jackson para especificar el tipo.
  3. 19

    Esta variante parece más simple y elegante.

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

    También estoy teniendo el mismo problema. Tengo un json que se puede convertir en objeto ArrayList.

    Cuenta este aspecto.

    Account{
      Person p ;
      Related r ;
    
    }
    
    Person{
        String Name ;
        Address a ;
    }

    Todos los de las clases anteriores se han anotado correctamente.
    He intentado TypeReference>() {}
    pero no está funcionando.

    Me da Arraylist pero ArrayList tiene un linkedHashMap que contiene algunos de los más vinculados hashmaps que contiene 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 he resuelto el problema. Soy capaz de convertir la Lista en la Cadena Json directamente a ArrayList como sigue:

    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 ;
        }  
    
    }
  5. 0

    Esto funciona para mí.

    @Test
    public void cloneTest() {
        List<Part> parts = new ArrayList<Part>();
        Part part1 = new Part(1);
        parts.add(part1);
        Part part2 = new Part(2);
        parts.add(part2);
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            String jsonStr = objectMapper.writeValueAsString(parts);
    
            List<Part> cloneParts = objectMapper.readValue(jsonStr, new TypeReference<ArrayList<Part>>() {});
        } catch (Exception e) {
            //fail("failed.");
            e.printStackTrace();
        }
    
        //TODO: Assert: compare both list values.
    }

Dejar respuesta

Please enter your comment!
Please enter your name here