Jackson 是一个流行的 JSON 处理库,用于在 Java 对象和 JSON 数据之间进行转换,在使用 Jackson 时,有时会遇到null
值导致的序列化或反序列化错误,以下是对 Jacksonnull
报错的详细分析:
1、报错原因
实体类中存在 null 属性:当使用 Jackson 将实体类转换为 JSON 时,如果实体类的属性值为 null,默认情况下会将该属性以null
的形式输出到 JSON 字符串中,但在某些场景下,前端组件可能无法正确处理包含null
值的 JSON 数据,从而导致报错。
集合中存在 null 元素:如果实体类中包含集合类型的属性,如 List、Map 等,并且集合中存在 null 元素,在序列化过程中也可能会引发null
相关的错误。
JSON 字符串中存在 null 值:当从 JSON 字符串反序列化为 Java 对象时,JSON 字符串中存在 null 值,而 Java 对象的对应属性类型不允许为 null,或者没有正确处理 null 值的逻辑,就会导致反序列化失败,抛出NullPointerException
等异常。
配置不当:如果没有正确配置 Jackson 的序列化和反序列化策略,可能会导致对null
值的处理不符合预期,从而引发错误,全局配置了不允许序列化 null 值,但在局部场景下又需要序列化 null 值,就可能出现报错的情况。
2、解决方法
实体类中使用注解
@JsonInclude(JsonInclude.Include.NON_NULL):将此注解放在实体类的属性上,如果该属性为 null 则不参与序列化;如果放在类上,则对该类的全部属性起作用。
public class User { @JsonInclude(JsonInclude.Include.NON_NULL) private String name; @JsonInclude(JsonInclude.Include.NON_NULL) private String house; // getter 和 setter 方法 }
@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL):在实体类前增加此注解,可以控制整个类的序列化行为,使其在属性为 null 时不进行序列化。
代码中设置 ObjectMapper
setSerializationInclusion:通过创建 ObjectMapper 对象,并调用其setSerializationInclusion
方法,设置序列化策略,设置为JsonInclude.Include.NON_NULL
,表示只序列化非 null 的属性:
ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); User user = new User(1, "", null); String outJson = mapper.writeValueAsString(user); System.out.println(outJson);
自定义序列化器:如果需要更灵活的控制序列化过程,可以自定义序列化器,对于 Map 中的 null key 或 value,可以通过继承 StdSerializer 类来实现自定义的序列化逻辑:
public static class NullKeySerializer extends StdSerializer<Object> { public NullKeySerializer() { this(null); } public NullKeySerializer(Class<Object> t) { super(t); } @Override public void serialize(Object nullKey, JsonGenerator jsonGenerator, SerializerProvider unused) throws IOException, JsonProcessingException { jsonGenerator.writeFieldName(""); } } // 使用方法 ObjectMapper mapper = new ObjectMapper(); mapper.getSerializerProvider().setNullKeySerializer(new NullKeySerializer()); Map<String, Object> map = new HashMap<>(); map.put(null, "test"); System.out.println(mapper.writeValueAsString(map));
全局配置:在 Spring Boot 项目中,可以通过新建配置类的方式来全局配置 Jackson 的行为,创建一个 JacksonConfig 类,并在其中配置 ObjectMapper 的NullValueSerializer
,将所有的 null 值转化为空字符串:
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.core.JsonGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import com.fasterxml.jackson.databind.annotation.JsonSerialize; public class JacksonConfig { @Bean @Primary @ConditionalOnMissingBean(ObjectMapper.class) public ObjectMapper jacksonObjectMapper() { return new ObjectMapper().setDefaultPropertyInclusion(JsonInclude.Include.NON_EMPTY); } }
3、相关问答FAQs
Q: 如果我只想在某个特定的字段上忽略 null 值,而在其他字段上正常处理 null 值,该怎么办?
A: 你可以在该特定字段上使用 @JsonInclude(JsonInclude.Include.NON_NULL) 注解,这样只有这个字段在为 null 时会被忽略,其他字段仍会按照默认的序列化规则进行处理。
Q: 在反序列化过程中,如果遇到 JSON 字符串中的 null 值,如何确保 Java 对象的对应属性不会被设置为 null?
A: 可以在实体类的属性上使用 @JsonSetter 注解,并提供一个自定义的setter方法来处理 null 值,在setter方法中,可以添加逻辑来避免将属性设置为 null,例如赋予默认值或进行其他处理。