Hay otro punto de vista para abordar este problema de manera más genérica para los objetos que serían deserializado usando BeanDeserializer, creando un BeanDeserializerModifier
y registrándolo con su asignador. BeanDeserializerModifier
es una especie de alternativa a la subclase BeanDeserializerFactory
, y le ofrece la posibilidad de devolver algo que no sea el deserializador normal que se usaría o de modificarlo.
Por lo tanto, primero cree un nuevo JsonDeserializer
que pueda aceptar otro deserializador cuando se está construyendo, y luego se aferra a ese serializador. En el método de deserialización, puede verificar si se le está pasando un JsonParser
que apunta actualmente a JsonToken.START_ARRAY
. Si no pasaste el JsonToken.START_ARRAY
, simplemente usa el deserializador predeterminado que se pasó a esta deserialización personalizada cuando se creó.
Finalmente, asegúrese de implementar ResolvableDeserializer
, para que el deserializador predeterminado esté correctamente conectado al contexto que está utilizando su deserializador personalizado.
class ArrayAsNullDeserialzer extends JsonDeserializer implements ResolvableDeserializer {
JsonDeserializer<?> mDefaultDeserializer;
@Override
/* Make sure the wrapped deserializer is usable in this deserializer's contexts */
public void resolve(DeserializationContext ctxt) throws JsonMappingException {
((ResolvableDeserializer) mDefaultDeserializer).resolve(ctxt);
}
/* Pass in the deserializer given to you by BeanDeserializerModifier */
public ArrayAsNullDeserialzer(JsonDeserializer<?> defaultDeserializer) {
mDefaultDeserializer = defaultDeserializer;
}
@Override
public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
JsonToken firstToken = jp.getCurrentToken();
if (firstToken == JsonToken.START_ARRAY) {
//Optionally, fail if this is something besides an empty array
return null;
} else {
return mDefaultDeserializer.deserialize(jp, ctxt);
}
}
}
Ahora que tenemos nuestro gancho deserializador genérico, creemos un modificador que pueda usarlo. Esto es fácil, simplemente implemente el método modifyDeserializer
en su BeanDeserializerModifier. Se le pasará el deserializador que sería se han utilizado para deserializar el frijol. También le pasa el BeanDesc que se deserializará, por lo que puede controlar aquí si desea o no manejar [] como nulo para todos los tipos.
public class ArrayAsNullDeserialzerModifier extends BeanDeserializerModifier {
@Override
public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
if (true /* or check beanDesc to only do this for certain types, for example */) {
return new ArrayAsNullDeserializer(deserializer);
} else {
return deserializer;
}
}
}
Finalmente, tendrá que registrar su BeanDeserializerModifier con su ObjectMapper. Para hacer esto, crea un módulo y agrega el modificador en la configuración (SimpleModules no parece tener un gancho para esto, desafortunadamente). Puede leer más sobre los módulos en otro lugar, pero aquí hay un ejemplo si aún no tiene un módulo para agregar a:
Module m = new Module() {
@Override public String getModuleName() { return "MyMapperModule"; }
@Override public Version version() { return Version.unknownVersion(); }
@Override public void setupModule(Module.SetupContext context) {
context.addBeanDeserializerModifier(new ArrayAsNullDeserialzerModifier());
}
};
Ok! Gracias, me imaginé que este sería el caso ... ¡nunca será fácil! ¿Conoces un buen tutorial sobre cómo escribir uno? – dardo
no hay oportunidad de arreglar la entrada original, ¿verdad? o, en el peor de los casos, si ese es el único caso, ¿qué pasa con una cadena reemplazar "[]" por "{}" – stivlo
Ojalá pudiera, es un servicio web que no tengo control, desde un campo de batalla malo sitio web de la compañía 2. – dardo