Jackson 的 NPE 试图序列化一个不存在的字段?
NPE from Jackson trying to serializing a field that does not exists?
这是我的简单 bean
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Foo {
private String firstName;
private String lastName;
public String getFullName(){
return firstName + lastName;
}
}
当此对象在 Spring-boot controller 中与 Jackson 序列化时,
我收到以下错误
j.l.NullPointerException: null
com.example.foobar.foo.getFullName(Foo.java:28)
s.r.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java)
s.r.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
s.r.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
j.l.reflect.Method.invoke(Method.java:498)
c.f.j.d.s.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:653)
c.f.j.d.s.s.BeanSerializerBase.serializeFields(BeanSerializerBase.java:690)..
28 common frames omitted\nWrapped by: c.f.j.d.JsonMappingException: (was java.lang.NullPointerException)
(through reference chain: com.example.foobar.foo[\"fullName\"])
c.f.j.d.JsonMappingException.wrapWithPath(JsonMappingException.java:379)
c.f.j.d.JsonMappingException.wrapWithPath(JsonMappingException.java:339)
c.f.j.d.s.s.StdSerializer.wrapAndThrow(StdSerializer.java:343)
c.f.j.d.s.s.BeanSerializerBase.serializeFields(BeanSerializerBase.java:698)
c.f.j.d.s.BeanSerializer.serialize(BeanSerializer.java:155)
c.f.j.d.s.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:292)
c.f.j.d.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1419)
c.f.j.d.ObjectWriter.writeValue(ObjectWriter.java:940)
o.s.h.c.j.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:267)...
23 common frames omitted\nWrapped by: o.s.h.c.HttpMessageNotWritableException: Could not write content: (was java.lang.NullPointerException) (through reference chain: com.example.foobar.foo[\"fullName\"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: com.example.foobar.foo[\"fullName\"])
o.s.h.c.j.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:274 ..."
这是我发送的requestBody
{"firstName": "foo",
"lastName: null
}
Jackson 是否在尝试序列化 fullName 属性?但我没有声明这样的字段。这是预期的行为吗?我找不到支持此行为的文档。
谢谢
您的猜测是正确的,Jackson 正试图通过其 getter 方法查找字段名称,但它找不到。因此 NPE。
不同的解决方案
- 对 getFullName 方法使用
@JsonIgnore
。
您可以通过在 spring 引导 application.properties 文件
中设置此 属性 来禁用此功能
spring.jackson.mapper.use-getters-as-setters=false
如果你想用 java 代码来做(如果不使用 spring 引导),你可以用这样的 bean 声明来做
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.featuresToDisable(MapperFeature.USE_GETTERS_AS_SETTERS);
return builder;
}
这是我的简单 bean
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Foo {
private String firstName;
private String lastName;
public String getFullName(){
return firstName + lastName;
}
}
当此对象在 Spring-boot controller 中与 Jackson 序列化时, 我收到以下错误
j.l.NullPointerException: null
com.example.foobar.foo.getFullName(Foo.java:28)
s.r.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java)
s.r.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
s.r.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
j.l.reflect.Method.invoke(Method.java:498)
c.f.j.d.s.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:653)
c.f.j.d.s.s.BeanSerializerBase.serializeFields(BeanSerializerBase.java:690)..
28 common frames omitted\nWrapped by: c.f.j.d.JsonMappingException: (was java.lang.NullPointerException)
(through reference chain: com.example.foobar.foo[\"fullName\"])
c.f.j.d.JsonMappingException.wrapWithPath(JsonMappingException.java:379)
c.f.j.d.JsonMappingException.wrapWithPath(JsonMappingException.java:339)
c.f.j.d.s.s.StdSerializer.wrapAndThrow(StdSerializer.java:343)
c.f.j.d.s.s.BeanSerializerBase.serializeFields(BeanSerializerBase.java:698)
c.f.j.d.s.BeanSerializer.serialize(BeanSerializer.java:155)
c.f.j.d.s.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:292)
c.f.j.d.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1419)
c.f.j.d.ObjectWriter.writeValue(ObjectWriter.java:940)
o.s.h.c.j.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:267)...
23 common frames omitted\nWrapped by: o.s.h.c.HttpMessageNotWritableException: Could not write content: (was java.lang.NullPointerException) (through reference chain: com.example.foobar.foo[\"fullName\"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: com.example.foobar.foo[\"fullName\"])
o.s.h.c.j.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:274 ..."
这是我发送的requestBody
{"firstName": "foo",
"lastName: null
}
Jackson 是否在尝试序列化 fullName 属性?但我没有声明这样的字段。这是预期的行为吗?我找不到支持此行为的文档。
谢谢
您的猜测是正确的,Jackson 正试图通过其 getter 方法查找字段名称,但它找不到。因此 NPE。
不同的解决方案
- 对 getFullName 方法使用
@JsonIgnore
。 您可以通过在 spring 引导 application.properties 文件
中设置此 属性 来禁用此功能spring.jackson.mapper.use-getters-as-setters=false
如果你想用 java 代码来做(如果不使用 spring 引导),你可以用这样的 bean 声明来做
@Bean public Jackson2ObjectMapperBuilder objectMapperBuilder() { Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); builder.featuresToDisable(MapperFeature.USE_GETTERS_AS_SETTERS); return builder; }