在 Spring Boot + Spring Data Rest 中反序列化时忽略带有 @JsonProperty 的字段

Posted

技术标签:

【中文标题】在 Spring Boot + Spring Data Rest 中反序列化时忽略带有 @JsonProperty 的字段【英文标题】:Fields with @JsonProperty are ignored on deserialization in Spring Boot + Spring Data Rest 【发布时间】:2015-06-23 22:26:52 【问题描述】:

我发现在 Spring Boot + Spring Data Rest 中,带有 @JsonProperty 的字段在反序列化时仍然被忽略。在不使用 Spring Boot 的情况下,该错误已得到修复。查看问题跟踪器:https://jira.spring.io/browse/DATAREST-320

我创建了一个最小的演示项目来重现 Spring Boot 1.2.3.RELEASE 中的错误。快捷方式:https://github.com/cdcorg/JsonPropertyBug/blob/master/src/main/java/demothree/domain/Entity.java#L21

启用@JsonProperty 将无法更改属性(通过使用HTTP PUT)

如果我设置

spring.jackson.mapper.USE_ANNOTATIONS=false

并尝试更新属性,Spring Data Rest 会说:


"cause": 
    "cause": 
        "cause": null,
        "message": "Unrecognized field "family" (class demothree.domain.Entity), 
        not marked as ignorable (3 known properties: "fname", "id", "name"])n at [Source: N/A; line: -1, column: -1] (through reference chain: demothree.domain.Entity["family"])"
    ,
    "message": "Could not read payload!; 
    nested exception is com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: 
    Unrecognized field "family" (class demothree.domain.Entity), 
    not marked as ignorable (3 known properties: "fname", "id", "name"])n at [Source: N/A; line: -1, column: -1] (through reference chain: demothree.domain.Entity["family"])"
,
"message": "Could not read an object of type class demothree.domain.Entity from the request!; 
nested exception is org.springframework.http.converter.HttpMessageNotReadableException: Could not read payload!; 
nested exception is com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "family" (class demothree.domain.Entity), not marked as ignorable 
(3 known properties: "fname", "id", "name"])n at [Source: N/A; line: -1, column: -1] (through reference chain: demothree.domain.Entity["family"])"

堆栈跟踪:

2015-04-16 11:50:00.391 ERROR 8420 --- [nio-8080-exec-5] s.d.r.w.AbstractRepositoryRestController : Could not read an object of type class demothree.domain.Entity from the request!; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: Could not read payload!; nested exception is com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "family" (class demothree.domain.Entity), not marked as ignorable (3 known properties: "fname", "id", "name"])
 at [Source: N/A; line: -1, column: -1] (through reference chain: demothree.domain.Entity["family"])

org.springframework.http.converter.HttpMessageNotReadableException: Could not read an object of type class demothree.domain.Entity from the request!; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: Could not read payload!; nested exception is com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "family" (class demothree.domain.Entity), not marked as ignorable (3 known properties: "fname", "id", "name"])
 at [Source: N/A; line: -1, column: -1] (through reference chain: demothree.domain.Entity["family"])
    at org.springframework.data.rest.webmvc.config.PersistentEntityResourceHandlerMethodArgumentResolver.readPutForUpdate(PersistentEntityResourceHandlerMethodArgumentResolver.java:197)
    at org.springframework.data.rest.webmvc.config.PersistentEntityResourceHandlerMethodArgumentResolver.read(PersistentEntityResourceHandlerMethodArgumentResolver.java:169)
    at org.springframework.data.rest.webmvc.config.PersistentEntityResourceHandlerMethodArgumentResolver.resolveArgument(PersistentEntityResourceHandlerMethodArgumentResolver.java:125)
    at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77)
    at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:162)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:129)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:776)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
    at org.springframework.web.servlet.FrameworkServlet.doPut(FrameworkServlet.java:879)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:516)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1086)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:659)
    at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1558)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1515)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.http.converter.HttpMessageNotReadableException: Could not read payload!; nested exception is com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "family" (class demothree.domain.Entity), not marked as ignorable (3 known properties: "fname", "id", "name"])
 at [Source: N/A; line: -1, column: -1] (through reference chain: demothree.domain.Entity["family"])
    at org.springframework.data.rest.webmvc.json.DomainObjectReader.merge(DomainObjectReader.java:137)
    at org.springframework.data.rest.webmvc.json.DomainObjectReader.readPut(DomainObjectReader.java:129)
    at org.springframework.data.rest.webmvc.config.JsonPatchHandler.applyPut(JsonPatchHandler.java:133)
    at org.springframework.data.rest.webmvc.config.PersistentEntityResourceHandlerMethodArgumentResolver.readPutForUpdate(PersistentEntityResourceHandlerMethodArgumentResolver.java:194)
    ... 45 common frames omitted
Caused by: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "family" (class demothree.domain.Entity), not marked as ignorable (3 known properties: "fname", "id", "name"])
 at [Source: N/A; line: -1, column: -1] (through reference chain: demothree.domain.Entity["family"])
    at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:51)
    at com.fasterxml.jackson.databind.DeserializationContext.reportUnknownProperty(DeserializationContext.java:744)
    at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:915)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1306)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1284)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:211)
    at com.fasterxml.jackson.databind.ObjectReader._bindAndClose(ObjectReader.java:1271)
    at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:971)
    at org.springframework.data.rest.webmvc.json.DomainObjectReader.doMerge(DomainObjectReader.java:191)
    at org.springframework.data.rest.webmvc.json.DomainObjectReader.merge(DomainObjectReader.java:135)
    ... 48 common frames omitted

谁能证实这一点?非常感谢任何帮助!

编辑:错字

【问题讨论】:

【参考方案1】:

一个很奇怪的解决方案:

在我切换回 Spring Data Rest 2.2.1(包含在 Spring Boot 1.2.1.RELEASE 中)后,HTTP PUT 现在可以正常工作。您可以通过更改我的错误演示项目的 POM 文件来验证这一点。

现在我很困惑: 为什么我没有像 Runar Botten 那样使用 Spring Data Rest 2.2.1 重现相同的错误? 为什么我使用后面的版本(2.2.2)会遇到这个错误??

【讨论】:

以上是关于在 Spring Boot + Spring Data Rest 中反序列化时忽略带有 @JsonProperty 的字段的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot实践——事件监听

Spring Boot Dataway 配置多数据库源

Spring Boot Dataway 配置多数据库源

Spring Boot,Spring Data JPA多数据源支持配置

spring-boot 执行器刷新和内存数据库

spring boot 配置全局日期类型转换器