我的春季启动应用程序中有以下控制器:
@RequestMapping(method = RequestMethod.POST)
public ResponseEntity<ResponseDto<MyClass> process(@RequestBody RequestDto<MyClass> request){
return null;
}
MyClass
有一个字段,让我们说“myField&#39;我希望对此字段的请求和响应有不同的NamingStrategy
配置(这是因为我不想为一个字段创建一个新类)。我已将ObjectMapper
实例配置如下:
@Bean
public ObjectMapper objectMapper(){
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setPropertyNamingStrategy(namingStrategy);
return objectMapper;
}
这将用于请求和响应(即反序列化和序列化),春季启动中是否有任何方法可以指示控制器使用不同的ObjectMapper
实例?
答案 0 :(得分:2)
您可以使用 content negotiation 解决此问题。首先,定义您的自定义 HttpMessageConverter 。在以下示例中,我定义了在请求Content-Type
标头设置为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));
}
为了简化此示例,我使用了新创建的ObjectMapper
- 在您的情况下,您必须在此处传递先前配置的对象。
接下来就是告诉你的行动只接受appliction/test+json
个请求(请记住,从现在起它需要Content-Type:application/test+json
标头出现在每个请求到这个端点的地方):
@RequestMapping(method = RequestMethod.POST, consumes = "application/test+json")
public ResponseEntity<ResponseDto<MyClass> process(@RequestBody RequestDto<MyClass> request){
return null;
}
最后一件事是确保在调用此端点时设置Content-Type:application/test+json
标头。当然,您可以使用任何其他名称作为所需的内容类型,显示的名称只是一个示例。
答案 1 :(得分:0)
一个肮脏的黑客:您可以为MyClass编写自定义序列化器和反序列化器,在那里您明确使用两个单独的对象映射器一个用于序列化(用于响应),第二个用于反序列化(用于请求)。
但是找到一种明确定制spring object mapper的方法会更好。
答案 2 :(得分:0)
您可以在ObjectMapper中使用反序列化修饰符,以通过模块覆盖对象反序列化时启用的功能集。这个应该做的伎俩:
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);
}
}
}
您必须将它与ObjectMapper一起注册为如下模块:
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.setDeserializerModifier(new FeatureModifyingBeanDeserializerModifer(Arrays.asList(Journey.class)));
objectMapper.registerModule(module);
对于序列化,您可以将@JsonSerialize注释添加到Journey类,并以您想要的任何方式对其进行序列化。如果您需要编写非转义字符串,可以使用JsonGenerator中的writeRaw。