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.

¿Cómo puedo hacer que la información de tipo sea visible para la deserialización de Jackson de manera condicional?

Estoy escribiendo código que trabaja con varios tipos de mensajes de cuerpo, los cuales pueden ser extendidos por complementos. Debido a que algunas de las infraestructuras podrían no conocer sobre tipos específicos, quiero tener una clase genérica de respaldo que pueda contener un objeto deserializado “cualquier cosa”. Intenté esto:

@JsonTypeInfo(use = NAME, visible = true, defaultImpl = UnknownBody)
abstract class Body {
    @NotNull
    String text
}

class UnknownBody extends Body {
    @JsonProperty('@type')
    String _bodyType

    @JsonAnyGetter
    @JsonAnySetter
    Map<string, object=""> _properties = new HashMap<>()
}

Esto funciona, pero cuando intento deserializar un subtipo de Body conocido, obtengo una excepción que indica que la propiedad @type no se encuentra en ellos. Así que intenté dividir la directiva @JsonTypeInfo:

@JsonTypeInfo(use = NAME, defaultImpl = UnknownBody)
abstract class Body {
    @NotNull
    String text
}

@JsonTypeInfo(use = NAME, visible = true)
class UnknownBody extends Body {
    @JsonProperty('@type')
    String _bodyType

    @JsonAnyGetter
    @JsonAnySetter
    Map<string, object=""> _properties = new HashMap<>()
}

Esto resulta en un valor null para _bodyType; aparentemente la información del tipo se elimina del deserializador temprano en el proceso.

¿Existe una forma adecuada de explicarle a Jackson que quiero que el discriminador de tipo se establezca en la clase UnknownBody sin hacer que falle en otras subclases y sin usar ignoreUnknown, lo cual podría causar un manejo incorrecto silencioso en otros subtipos?</string,></string,>

Tags:  , ,

Answer

  1. Avatar for davy.ai

    El problema aquí es que cuando la anotación @JsonTypeInfo se divide entre la clase abstracta Body y la clase concreta UnknownBody, Jackson solo aplica la información de tipo a UnknownBody y no a ninguna de sus subclases. Una forma de resolver este problema es mover la anotación @JsonTypeInfo a una clase abstracta separada de la cual Body y UnknownBody hereden, de la siguiente manera:

    @JsonTypeInfo(use = NAME, visible = true, defaultImpl = UnknownBody.class)
    abstract class BodyWithType {
        @JsonProperty("@type")
        String type;
    }
    
    @JsonTypeInfo(use = NAME, visible = true)
    class UnknownBody extends BodyWithType {
        @JsonAnyGetter
        @JsonAnySetter
        Map<string, object=""> properties = new HashMap<>();
    }
    
    abstract class Body extends BodyWithType {
        @NotNull
        String text;
    }
    

    Ahora cualquier subclase de Body heredará la anotación @JsonTypeInfo y obtendrá la propiedad type correcta al deserializarse, mientras que UnknownBody aún puede manejar propiedades arbitrarias utilizando @JsonAnyGetter y @JsonAnySetter.

    Ten en cuenta que hemos utilizado una clase abstracta separada llamada BodyWithType para evitar llenar la clase Body con la anotación @JsonTypeInfo. Esto también nos permite usar defaultImpl para especificar la clase UnknownBody como alternativa en caso necesario, lo cual no habría sido posible si mantuviéramos la anotación @JsonTypeInfo en Body.

    Este enfoque debería manejar escenarios en los que tienes una combinación de tipos de Body conocidos y desconocidos, sin requerir ignoreUnknown y arriesgar la manipulación incorrecta de otros subtipos.</string,>

Comments are closed.