【问题标题】:Jackson: get a null reference on deserializing杰克逊:获得关于反序列化的空参考
【发布时间】:2017-08-28 11:50:51
【问题描述】:

我将 spring-mvc 用于restful 服务。通过添加依赖项,我的休息控制器会自动从我的response entitiesgenerate json

依赖关系

jackson = '2.9.0'
compile "com.fasterxml.jackson.core:jackson-databind:$jackson"

对象

@Getter @Setter
public final class UserDTO {
    [...]

    private int id;
    private Set<ActivityDTO> activities = Sets.newHashSet();
}


@Getter @Setter
public final class ActivityDTO {
    [...]

    private int id;
    private Set<ActivityDTO> subActivities;
}

问题

问题出现在special cases。例如,我想将activity 添加到user。以下user-json works好,Jackson converts it without error.

{
"id": 1,
  "activities": [
    {
      "id": 1,
      "subActivities": null,
    }
  ]
}

但是如果我添加一个带有子活动的活动,它就会崩溃!

{
  "id": 6,
  "activities": [
    {
      "id": 19,
      "subActivities": [
        {
          "id": 20,
          "subActivities": [
            {
              "id": 24,
              "subActivities": null
            },
            {
              "id": 21,
              "subActivities": [
                {
                  "id": 23,
                  "subActivities": null
                },
                {
                  "id": 22,
                  "subActivities": null
                }
              ]
            }
          ]
        }
      ],
    }
  ]
}

确实,jackson can't deserialize 这个 json,我不明白为什么。我收到以下错误..有什么想法吗?

13:45:56.890 [http-nio-8080-exec-1] DEBUG org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod - Failed to resolve argument 0 of type 'com.ortec.gta.database.model.dto.UserDTO'
org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: (was java.lang.NullPointerException); nested exception is com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: com.ortec.gta.database.model.dto.UserDTO["activities"]->java.util.HashSet[2]->com.ortec.gta.database.model.dto.ActivityDTO["subActivities"]->java.util.HashSet[0]->com.ortec.gta.database.model.dto.ActivityDTO["subActivities"])
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:238)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:223)
    at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:201)
    at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:150)
    at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:128)
    at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
    at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:158)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doPut(FrameworkServlet.java:883)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:664)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter.doFilter(OAuth2AuthenticationProcessingFilter.java:176)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at com.ortec.gta.configuration.ServletInitializer$CorsFilter.doFilter(ServletInitializer.java:78)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:624)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    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:748)
Caused by: com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: com.ortec.gta.database.model.dto.UserDTO["activities"]->java.util.HashSet[2]->com.ortec.gta.database.model.dto.ActivityDTO["subActivities"]->java.util.HashSet[0]->com.ortec.gta.database.model.dto.ActivityDTO["subActivities"])
    at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:391)
    at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:351)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.wrapAndThrow(BeanDeserializerBase.java:1689)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:370)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:285)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:244)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:27)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:368)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:285)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:244)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:27)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:368)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3072)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:235)
    ... 77 common frames omitted
Caused by: java.lang.NullPointerException: null
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:271)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:244)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:27)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:368)
    ... 93 common frames omitted

这里是所有字段的对象,可能与我的错误有关?

@Getter @Setter
public final class ActivityDTO {
    private int id;
    private String name;
    private long creationDate;
    private long modificationDate;
    private long deletionDate;
    @JsonIgnoreProperties(value = {"activities"})
    private UserDTO lastEditor;
    @JsonIgnoreProperties(value = {"subActivities", "users", "parentActivity"})
    private ActivityDTO parentActivity;
    @JsonIgnoreProperties(value = {"parentActivity"})
    private Set<ActivityDTO> subActivities;
    @JsonIgnoreProperties(value = {"activities"})
    private Set<UserDTO> users;
    private String code;
    private boolean active;
}

@Getter @Setter
public final class UserDTO {
    private int id;
    private String username;
    private String name;
    private String lastname;
    private byte[] avatar;
    private String email;
    @JsonIgnoreProperties(value = {"activities", "activities"})
    private UserDTO superior;
    private Set<RoleDTO> roles;
    @JsonIgnoreProperties(value = {"users", "parentActivity"})
    private Set<ActivityDTO> activities;
}

@Getter @Setter
public final class RoleDTO {
    private Integer id;
    private String name;
}

【问题讨论】:

  • 您的问题不能用给定的类和 json 重现。它确实落在那个“,”上,没有它也能正常工作。
  • 它不适合我...
  • @chimmi 用完整的对象编辑了我的主题
  • @Bean public ObjectMapper objectMapper() { ObjectMapper objectMapper = new ObjectMapper();返回对象映射器;将 thi bean 添加到您的配置文件中,并将 @JsonIgnoreProperties(ignoreUnknown=true) 添加到您的 pojo 类中;
  • @boukobbaadil 让我试试 ;)

标签: java spring jackson


【解决方案1】:

首先,这看起来像是 Jackson 中的一个错误,因为错误只出现在版本 2.8.0 及更高版本中。

至于错误的来源,看来是你对ActivityDTO的配置,特别是这个注解:

@JsonIgnoreProperties(value = {"parentActivity"})
private Set<ActivityDTO> subActivities;

所以你有 3 个选择:

  1. 回滚到 Jackson 2.7.9
  2. 为此案例制作自定义反序列化器
  3. 删除此注释并使用自定义序列化程序(如果需要)

【讨论】:

  • 回滚到 2.7.9 已全部修复 :) 非常感谢
  • 不客气,别忘了用完整的 POJO 更新你的 github issue,这样他们也可以重现它。
  • 啊哈是的,我刚刚链接了这个话题!
【解决方案2】:

当我发现这个错误是因为我像你一样使用原始类型

尝试使用可为空的属性

@Getter @Setter    
public final class ActivityDTO {
    private Integer id;
    private String name;
    private Long creationDate;
    private Long modificationDate;
    private Long deletionDate;

【讨论】:

    【解决方案3】:

    这是因为你有一个额外的“,”字符,这使得你的 json 无效。它在您的 json 末尾:],。删除“,”,它应该可以工作。

    【讨论】:

    • 让我现在试试
    • 我从您的帖子中获取了 JSON。我使用了一个在线格式化程序,例如jsonformatter.curiousconcept.com 在它的当前形状中,它会抛出一个解析错误(所以我希望看到你看到的错误是正常的)。如果我删除“,”,那么它解析OK。你能确定你删除了正确的“,”吗? (JSON 末尾的第四个非空白字符)。另外,错误保持不变,还是改变了?
    • 我编辑了我的json来删除多余的数据,原来的json没有问题; gist.github.com/Romain-P/d4e81ee1d272b7f56ba7db6c730c7b4b
    【解决方案4】:
    @Bean
        public ObjectMapper objectMapper() {
            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper;
        }
    

    将此bean添加到您的配置文件并添加

    @JsonIgnoreProperties(ignoreUnknown=true)
    

    到你的 pojo 课程;

    【讨论】:

    • 它没有解决问题.. + 如果jackson在依赖项中导入,spring会自动创建ObjectMapper +一些配置。您的注释也没有帮助!还是谢谢
    • 如果 pojo 类来自第三方库,如果不是 POJO 则最糟糕?
    • 如果那个 pojo 来自第三方库并且我们不能添加 JsonIgnoreProperties 注释呢?
    【解决方案5】:

    我认为这不是 Jackson 的错误。就我而言,使用注释在所有级联类上的 @JsonIgnoreProperties 上添加 allowSetters = true 有助于解决此问题。

    【讨论】:

      猜你喜欢
      • 2011-08-21
      • 2015-04-07
      • 1970-01-01
      • 2014-09-29
      • 1970-01-01
      • 2012-11-19
      • 2016-10-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多