Quiero convertir una cadena JSON en java objeto, pero la clase de este objeto contiene el resumen de los campos, que Jackson no se puede instanciar, y no produce el objeto. ¿Cuál es la forma más fácil de saber es acerca de algunos implementación predeterminada de una clase abstracta, como

setDefault(AbstractAnimal.class, Cat.class);

o para decidir acerca de la clase de implementación basado en JSON nombre de atributo, por ejemplo. para un objeto JSON:

{
    ...
    cat: {...}
    ...
}

acabo de lanzamiento del sitio:

setImpl("cat", Cat.class);


Sé que es posible en Jackson para incrustar información de clase dentro de JSON, pero no quiero complicar el formato JSON que yo uso. Quiero decidir qué clase a utilizar sólo por el ajuste predeterminado de la clase de implementación, o por el nombre del atributo (‘gato’) – como en XStream de la biblioteca, donde se escribe:

xStream.alias("cat", Cat.class);

Hay una manera de hacerlo, sobre todo en una línea, o se requiere algo más de código?

  • No hay tal cosa como un ‘resumen de campo’ en Java.
  • lo que quiero decir es: class C { Animal animal; } y quiero crear una instancia de C, donde Aniaml es abstracta, y quiero poner en este campo un Gato, que se extiende de los Animales
  • así que no hay problema. No hay ninguna regla en contra de variables de tipos abstractos.
  • Se se es posible incrustar información de clase dentro de JSON: @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "type"). Ver comentarios en el stackoverflow.com/a/32777371/873282
InformationsquelleAutor Marcin | 2011-03-30

4 Comentarios

  1. 40

    Hay varias maneras; antes de la versión 1.8, forma más sencilla es probablemente hacer:

    @JsonDeserialize(as=Cat.class)
    public abstract class AbstractAnimal { ... }

    como para decidir basado en atributos, que se hace mejor uso de @JsonTypeInfo, que hace automático embeddeding (al escribir) y el uso de información de tipo.

    Hay varios tipos de información de tipo (nombre de la clase, tipo lógico nombre), así como la inclusión de mecanismos (como incluir la propiedad, como la-envoltura-de la matriz, como la-envoltura-objeto). Esta página: https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization explica algunos de los conceptos.

    • Gracias por la respuesta! @JsonDeserialize es lo que va a ser ideal para mi problema, ya que no requiere de la incrustación de cualquier tipo de información en JSON. Sin embargo no puedo usar esto, como no puedo modificar las clases que quiero crear instancias, como son parte de otros proyectos, y la modificación de este código, se podría romper otro código.
    • Las anotaciones también son bastante inflexibles, como yo no puede dinámicamente decidir qué aplicación puedo usar.
    • Respecto de la modificación de las clases, esto es lo que Jackson mezcla en las anotaciones se para. Pero correcta, esta anotación es sólo la intención de ser utilizado para los casos donde sólo hay un tipo de aplicación. Jackson 1.8 se tiene la funcionalidad de permitir que la simple tipo abstracto -> impl tipo de asignaciones, por lo que vale la pena.
    • mezclar en las anotaciones que hizo el trabajo, gracias por que apunta a la dirección correcta
    • Que bueno saber que trabajó.
    • Esto permite especificar sólo una clase? ¿Cuando hay 10 de ellos?
    • A continuación, usted desea utilizar polimórficos deserialización, generalmente a través de @JsonTypeInfo
    • Los enlaces de la wiki es la URL de nuevo parece ser github.com/FasterXML/jackson-docs/wiki/…

  2. 2

    Una de pleno derecho de respuesta con un ejemplo muy claro se puede encontrar aquí: https://stackoverflow.com/a/30386694/584947

    Jackson se refiere a esto como Polimórficos Deserialización.

    Me ayudo mucho con mi problema. Yo tenía una clase abstracta que me estaba guardando en una base de datos y necesarios para deserializar a un concreto instancia de una clase (es comprensible).

    Se le mostrará la manera correcta de anotar los padres de clase abstracta y cómo enseñar jackson cómo escoger entre los disponibles sub-clase de los candidatos en tiempo de ejecución cuando referencias y resolución de referencias.

  3. 0

    Si quieres contaminar ni su JSON con campos adicionales ni tus clases con la anotación, puede escribir una muy simple módulo y deserializer que usa el valor predeterminado de la subclase a la que usted desea. Es más de una línea debido a algún código repetitivo, pero todavía es relativamente simple.

    class AnimalDeserializer extends StdDeserializer<Animal> {
        public AnimalDeserializer() {
            super(Animal.class);
        }
    
        public Animal deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException {
            return jsonParser.readValueAs(Cat.class);
        }
    }
    
    class AnimalModule extends SimpleModule {
        {
            addDeserializer(Animal.class, new AnimalDeserializer());
        }
    }

    A continuación, registrar este módulo para la ObjectMapper y eso es todo (Zoo es la clase de contenedor que tiene un Animal de campo).

    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.registerModule(new AnimalModule());
    return objectMapper.readValue(json, Zoo.class);

Dejar respuesta

Please enter your comment!
Please enter your name here