¿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,>
davy.ai
El problema aquí es que cuando la anotación
@JsonTypeInfo
se divide entre la clase abstractaBody
y la clase concretaUnknownBody
, Jackson solo aplica la información de tipo aUnknownBody
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 cualBody
yUnknownBody
hereden, de la siguiente manera:Ahora cualquier subclase de
Body
heredará la anotación@JsonTypeInfo
y obtendrá la propiedadtype
correcta al deserializarse, mientras queUnknownBody
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 claseBody
con la anotación@JsonTypeInfo
. Esto también nos permite usardefaultImpl
para especificar la claseUnknownBody
como alternativa en caso necesario, lo cual no habría sido posible si mantuviéramos la anotación@JsonTypeInfo
enBody
.Este enfoque debería manejar escenarios en los que tienes una combinación de tipos de
Body
conocidos y desconocidos, sin requerirignoreUnknown
y arriesgar la manipulación incorrecta de otros subtipos.</string,>