Jackson 3 序列化枚举报 NPE,检查 toString 是否返回 null
枚举常量正常,只有某个标签为空时写 JSON 失败。Jackson 3 默认采用 toString 输出,需为值和 Map 键明确可用的协议表示。
Jackson 3 写枚举数组时抛出 DatabindException,内部是 SerializableString.appendQuoted 的空指针;开启枚举小写输出后,又变成 String.toLowerCase() 的空指针。若只有某个常量出错,检查它重写的 toString 是否返回 null。
Jackson 3 默认启用 EnumFeature.WRITE_ENUMS_USING_TO_STRING。枚举本身不为 null,也可能因为标签字段为空,导致 toString 返回 null。正式 3.2.4 的缓存构建仍会把这个结果交给小写转换或字符串编译,不能只在外围给数组加非空检查。
协议本来用常量名称,就明确选择 name
如果接口应该输出 RED、NONE 这样的枚举名称,而不是展示标签,可以在实际使用的 JsonMapper 上关闭 toString 输出:
import tools.jackson.databind.cfg.EnumFeature;
import tools.jackson.databind.json.JsonMapper;
JsonMapper mapper = JsonMapper.builder()
.disable(EnumFeature.WRITE_ENUMS_USING_TO_STRING)
.build();
整合时保留现有模块、命名策略与其他选项。字段上已有显式名称、枚举命名策略或自定义 serializer 时,还需核对实际优先级;不能仅凭这个开关就承诺所有枚举都逐字等于 name。
从 Red 变成 RED 会改变协议值。若接收方要求既有展示标签,不能为了消掉异常直接全局关闭特性,而应让每个常量提供符合接口的非空表示,或为目标字段安排明确的传输映射。
null 标签不等于 JSON null
NONE 是一个实际存在的枚举常量,null 引用则表示没有枚举对象。若业务希望 NONE 输出 JSON null,需要在传输层明确处理;把 toString 改为返回文字"null",输出的是字符串,不是 JSON 空值。
同样,空字符串可能原本就是一个有意义的协议值,不能随意用它填补所有缺失标签。枚举用作 Map 键时更要单独定义:JSON 对象键必须是字符串,值的 null 策略不能直接挪给键,否则可能产生冲突或丢项。
分别核对普通标签、缺失标签、小写设置、数组值及 Map 键。若使用从 JSON 读回的入口,同时确认它接受的是名称还是标签。Java 枚举正常构造,并不证明其展示方法能满足序列化协议。


