应统一使用jackson而非jdk原生序列化处理复杂集合对象,因其支持泛型、容错强、可配置日期格式和字段过滤,并提供typereference解决嵌套泛型反序列化问题。

在项目中处理复杂集合对象(比如 List<map object>></map>、嵌套泛型 Map<string list>></string> 或含自定义类型字段的 DTO)时,直接用 JDK 原生序列化不仅易出错、难调试,还缺乏灵活性和可维护性。真正“优雅”的做法是:**避开 ObjectOutputStream,统一用 Jackson(或 Gson),封装成可复用、带类型安全、容错强的工具方法**。
用 Jackson 封装通用 JSON 工具类
这是最常用也最推荐的方式。Jackson 灵活支持泛型、忽略未知字段、处理 null、兼容日期/枚举等,且生态成熟。
- 引入依赖(Maven):
<dependency><br> <groupid>com.fasterxml.jackson.core</groupid><br> <artifactid>jackson-databind</artifactid><br> <version>2.15.4</version><br></dependency>
- 初始化单例
ObjectMapper,配置关键选项:
— 关闭FAIL_ON_UNKNOWN_PROPERTIES(避免因新增字段反序列化失败)
— 启用WRITE_DATES_AS_TIMESTAMPS或自定义日期格式
— 注册JavaTimeModule支持LocalDateTime等新时间类型 - 提供泛型友好的方法,例如:
public static <t> T fromJson(String json, Class<t> clazz)</t></t>public static <t> T fromJson(String json, TypeReference<t> typeRef)</t></t>
后者专用于集合嵌套场景,如new TypeReference<list>>() {}</list>
处理含泛型的嵌套集合(如 Map>)
JDK 原生序列化无法保留泛型信息,反序列化后容易变成 LinkedHashMap,丢失类型。Jackson 的 TypeReference 是标准解法。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 错误写法(会丢失 Product 类型):
Map<string list> map = mapper.readValue(json, Map.class);</string> - 正确写法:
TypeReference<map list>>> type = new TypeReference<map list>>>() {};<br>Map<string list>> result = mapper.readValue(json, type);</string></map></map> - 可进一步封装为工具方法:
public static <k v> Map<k list>> toMapOfList(String json, Class<k> keyClass, Class<v> valueClass)</v></k></k></k>
内部用SimpleType.constructMapType(...)构建类型,调用readValue
对敏感字段与空值做统一控制
优雅不只是功能完整,还包括健壮性和可读性。实际项目中常需:
— 过滤 password、token 等字段(不序列化)
— 把 null 字段序列化为空字符串或跳过
— 统一驼峰转下划线(如 userName → user_name)
- 用注解控制:
@JsonIgnore(排除字段)@JsonInclude(JsonInclude.Include.NON_NULL)(全局或类级)@JsonProperty("user_name")(重命名) - 或在
ObjectMapper中全局配置:mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
避免踩坑:Serializable 不适合复杂集合场景
虽然 JDK 原生 Serializable 能序列化 ArrayList 或 HashMap,但它存在硬伤:
- 生成字节流体积大、不可读,调试困难;
- 泛型擦除导致反序列化后无法保证元素类型(运行时
List>); - 类结构变更(如增删字段)极易引发
InvalidClassException,除非手动维护serialVersionUID; - 不支持跨语言交互(前端、Python 服务无法解析);
- 无法按需忽略字段或格式化值(比如金额保留两位小数)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










