首页 文章

Spring MVC Rest Controller @RequestBody Parsing

提问于
浏览
2

我有一个Spring rest Web应用程序,其中包含一个通用的休息控制器,如下所示 . 在 Jackson 将对象序列化为JSON时,GET方法工作正常 . 但是,当我尝试调用save方法时,RequestBody参数将转换为LinkedHashMap而不是T泛型类型定义的类型 .

@RestController
public abstract class CrudAPI<T extends Object, ID extends Serializable>{

    @Transactional
    @RequestMapping(method = RequestMethod.POST, consumes = "application/json")
    public ResponseEntity<Void> save(@RequestBody T entity){
        service.save(entity);
        return new ResponseEntity(HttpStatus.CREATED);
    }

}

JSON:

{
   "id":null,
   "version":null,
   "name":"Copel",
   "disabled":false,
   "type":"P",
   "labels":[
      {
         "id":null,
         "version":null,
         "name":"unidade consumidora"
      }
   ]
}

我收到以下错误:

HTTP状态500 - 请求处理失败;嵌套异常是org.springframework.beans.NotReadablePropertyException:bean类的无效属性'version'[java.util.LinkedHashMap]:在回退访问期间无法找到属性的字段!

Spring配置:

@Configuration
@Import(Application.class)
@EnableWebMvc
@ComponentScan(basePackages = {"br.com.doc2cloud"})
public class WebConfig extends WebMvcConfigurerAdapter implements WebApplicationInitializer {

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    private MappingJackson2HttpMessageConverter jacksonConverter() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new Hibernate5Module());
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        mapper.setDateFormat(new ISO8601DateFormat());
        mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE);
        mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        MappingJackson2HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter();
        jacksonConverter.setObjectMapper(mapper);

        return jacksonConverter;
    }

 @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(jacksonConverter());
        super.configureMessageConverters(converters);
    }

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        servletContext.setInitParameter("javax.servlet.jsp.jstl.fmt.localizationContext", "messages");
        EnumSet<DispatcherType> dispatcherTypes = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD);
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        characterEncodingFilter.setForceEncoding(true);
        FilterRegistration.Dynamic characterEncoding = servletContext.addFilter("characterEncoding", characterEncodingFilter);
        characterEncoding.addMappingForUrlPatterns(dispatcherTypes, true, "/*");
    }
}

我的代码出了什么问题?

2 回答

  • 2

    您使用的是哪个版本的 Jackson ?我升级到2.7.3并且在使用泛型时(我有一个基本控制器,具有用于保存,列表等的通用逻辑),我遇到了同样的问题 . 回滚到2.6.5允许我继续使用我的通用基类 . 我还没有研究过这个问题的原因,但是回头修复了它 .

  • 1

    我认为你不能达到你想要的效果 . Java泛型机制仅在编译时起作用 . 编译后,泛型类型将被删除并被实际类型替换(在您的情况下为 Object ) . 您的控制器无法理解您尝试解析JSON数据的类型 .

    你得到 LinkedHashMap 的原因是 Jackson 默认使用"unknown"类型 . 典型的JSON数据实际上是一个键值映射,Jackson保留了属性排序 - 这就是使用 linked 哈希映射的原因 .

相关问题