Tengo el siguiente controlador en mi aplicación Spring Boot:
@RequestMapping(method = RequestMethod.POST) public ResponseEntity<ResponseDto<MyClass> process(@RequestBody RequestDto<MyClass> request){ return null; } MyClass tiene un campo, digamos 'myField' y quiero una configuración diferente de NamingStrategy para solicitud y respuesta para este campo (esto se debe a que no quiero crear una nueva clase solo para un campo). He configurado la instancia de ObjectMapper de la siguiente manera:
@Bean public ObjectMapper objectMapper(){ ObjectMapper objectMapper = new ObjectMapper(); objectMapper.setPropertyNamingStrategy(namingStrategy); return objectMapper; } Esto se usará tanto para Solicitud como para Respuesta (es decir, deserialización y serialización), ¿hay alguna forma en el arranque de primavera por la cual pueda indicarle al controlador que use diferentes instancias de ObjectMapper ?
Puedes resolverlo con negociación de contenido . En primer lugar, defina su HttpMessageConverter personalizado. En el siguiente ejemplo, he definido un convertidor personalizado que se aplica cuando el encabezado Content-Type la solicitud se establece en application/test+json :
@Bean public HttpMessageConverters customConverters() { final AbstractJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(new ObjectMapper()); converter.setSupportedMediaTypes(Collections.singletonList(MediaType.valueOf("application/test+json"))); return new HttpMessageConverters(true, Collections.singletonList(converter)); } Para simplificar este ejemplo, he usado ObjectMapper recién creado; en su caso, tendrá que pasar aquí el objeto previamente configurado.
Lo siguiente es decirle a su acción que acepte solo solicitudes de appliction/test+json (tenga en cuenta que, a partir de ahora, requiere que el Content-Type:application/test+json se presente en cada solicitud a este punto final):
@RequestMapping(method = RequestMethod.POST, consumes = "application/test+json") public ResponseEntity<ResponseDto<MyClass> process(@RequestBody RequestDto<MyClass> request){ return null; } Lo último es asegurarse de que cuando llame a este punto final, se establezca el encabezado Content-Type:application/test+json . Por supuesto, puede usar cualquier otro nombre para el tipo de contenido deseado, el nombre presentado es solo un ejemplo.
Puede usar un modificador de deserialización en su ObjectMapper para anular el conjunto de funciones habilitadas en el momento de la deserialización del objeto a través de un módulo. Este debería hacer el truco:
public class FeatureModifyingBeanDeserializerModifier extends BeanDeserializerModifier { private Collection<Class<?>> modifiedClasses; public FeatureModifyingBeanDeserializerModifier(Collection<Class<?>> modifiedClasses) { this.modifiedClasses = Collections.unmodifiableSet(new HashSet<Class<?>>(modifiedClasses)); } @Override public JsonDeserializer<?> modifyDeserializer( DeserializationConfig config, BeanDescription beanDesc, final JsonDeserializer<?> deserializer) { JsonDeserializer<?> result = deserializer; Class<?> beanClass = beanDesc.getBeanClass(); if (modifiedClasses.contains(beanClass)) { result = new FeatureModifyingStdDeserializer(deserializer, beanClass); } return result; } private static class FeatureModifyingStdDeserializer extends StdDeserializer<Object> { private JsonDeserializer<?> deserializer; private FeatureModifyingStdDeserializer( JsonDeserializer<?> deserializer, Class<?> beanClass) { super(beanClass); this.deserializer = deserializer; } @Override public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { p.enable(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER); return deserializer.deserialize(p, ctxt); } } }Tienes que registrarlo con ObjectMapper como un módulo como este:
ObjectMapper objectMapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.setDeserializerModifier(new FeatureModifyingBeanDeserializerModifer(Arrays.asList(Journey.class))); objectMapper.registerModule(module);Para la serialización, puede agregar una anotación @JsonSerialize a la clase Journey y serializarla de la forma que desee. Si necesita escribir una cadena sin escape, puede usar writeRaw de JsonGenerator.
Un truco sucio: puede escribir un serializador y deserializador personalizado para MyClass, allí usa explícitamente dos mapeadores de objetos separados, uno para serialización (para respuesta) y el segundo para deserialización (para solicitud).
Pero es mejor encontrar una manera de personalizar explícitamente el mapeador de objetos de primavera.