es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Deserializar una lista de objetos con Jackson

Tengo una lista de objetos, cada uno de ellos tiene campos especificados (tipo de variable), así que pensé en crear una clase principal (super clase) con los elementos compartidos (variables) y dos subclases para el tipo específico de variables.
Quiero deserializar todas las subclases como el tipo de la superclase para poder poner todos estos objetos Json en una lista de los mismos objetos.

Aquí tienes un ejemplo de mi Json.

[   { "query": "edad",        "type": "numérico", "min": 5, "max": 99 },
 { "query": "diagnóstico",  "type": "cadena",  "in": ["tos",
 "resfriado"] } ]

El código que escribí para deserializar esto es:

public class Query{
    private String query;
    private String type;
    // Getters y Setters y constructor
}

public class QueryString extends Query implements Serializable {
    private List<string> in;
    private String like;
    // Getters y Setters y constructor
}

public class QueryNum extends Field implements Serializable {
    private Number min;
    private Number max;
    // Getters y Setters y constructor
}

La serialización utilizando ObjectMapper funciona como se esperaba, pero al deserializar, el compilador me da que hay valores no reconocidos (que son los campos de mis subclases).

Quiero obtener una lista de objetos (Query) List que contiene QueryString y QueryNum.

¿Es posible hacer eso con Jackson Json en Java?

Para la deserealización utilicé:

ObjectMapper mapper = new ObjectMapper();

List<query> queries = Arrays.asList(mapper.readValue(JsonString, Query[].class));

Gracias de antemano.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Sí, es posible deserializar subclases como el tipo de su superclase utilizando Jackson JSON en Java. Puedes utilizar la anotación @JsonTypeInfo y sus variantes para indicarle a Jackson que el JSON contiene información sobre la clase real del objeto que se está deserializando. Así es cómo puedes modificar tu código para lograr esto:

    1. Agrega la anotación @JsonTypeInfo a tu superclase Query:

      @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = “type”)
      public class Query implements Serializable {
      // …
      }

    Esto le dice a Jackson que incluya una propiedad “type” en el JSON, la cual especifica la clase real del objeto que se va a deserializar.

    1. Agrega la anotación @JsonSubTypes a tus subclases QueryString y QueryNum:

      @JsonSubTypes({
      @JsonSubTypes.Type(name = “string”, value = QueryString.class),
      @JsonSubTypes.Type(name = “numeric”, value = QueryNum.class)
      })
      public class QueryString extends Query implements Serializable {
      // …
      }

      @JsonSubTypes({
      @JsonSubTypes.Type(name = “numeric”, value = QueryNum.class),
      @JsonSubTypes.Type(name = “string”, value = QueryString.class)
      })
      public class QueryNum extends Query implements Serializable {
      // …
      }

    Esto le dice a Jackson qué subclase corresponde a cada posible valor de la propiedad “type” en el JSON.

    1. Modifica tu código de deserialización para utilizar un ObjectMapper configurado con los ajustes necesarios:

      ObjectMapper mapper = new ObjectMapper();
      mapper.enableDefaultTyping();
      List queries = mapper.readValue(jsonString, new TypeReference<>>() {});

    El método enableDefaultTyping le indica a Jackson que incluya la información de tipo necesaria en el JSON, y el TypeReference permite a Jackson determinar correctamente el tipo de la lista que se está deserializando.

    Con estas modificaciones, tu código debería ser capaz de deserializar el JSON en una lista de Query que contiene instancias de QueryString y QueryNum según corresponda.

Comments are closed.