反射是JSON库的隐形引擎,用于动态获取字段、调用getter/setter、处理注解与泛型;开发者只需提供无参构造、标准JavaBean结构及合理注解,无需手动写反射代码。

Java 反射机制本身不直接参与 JSON 序列化,但它被主流 JSON 库(如 Jackson、Gson、Fastjson)底层广泛使用,来动态读取字段、调用 getter/setter、处理泛型和注解。你不需要手动写反射代码去“结合”它们——只要按规范定义类、合理使用注解,库会自动利用反射完成对象与 JSON 的转换。
反射在 JSON 库中起什么作用
JSON 库需要在运行时:
- 获取类的 字段名、类型、修饰符(通过
Class.getDeclaredFields()等) - 判断是否忽略某个字段(检查
@JsonIgnore、@Transient等注解) - 访问私有字段或调用私有 setter(通过
field.setAccessible(true)) - 处理泛型类型(如
List),需借助ParameterizedType和反射提取实际类型参数 - 查找并调用无参构造方法创建实例(
clazz.getDeclaredConstructor().newInstance())
如何让自定义类更好支持反射驱动的 JSON 转换
关键不是写反射代码,而是让类对反射友好:
-
提供无参构造函数:Jackson/Gson 默认需要它来实例化对象;若只有带参构造,需配合
@JsonCreator(Jackson)或@SerializedName+ 自定义反序列化器 -
字段尽量设为 public 或提供标准 getter/setter:避免过度依赖
setAccessible,提升可维护性和安全性 -
用注解控制序列化行为:
- Jackson:
@JsonProperty("user_name")、@JsonIgnore、@JsonFormat(pattern="yyyy-MM-dd") - Gson:
@SerializedName("user_name")、@Expose(需配置GsonBuilder.excludeFieldsWithoutExposeAnnotation())
- Jackson:
-
避免非静态内部类:它隐含持有外部类引用,反射实例化时可能抛
InstantiationException;改用静态内部类或独立类
手写反射辅助 JSON 处理的典型场景(慎用)
极少数情况下需主动用反射补位,例如:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
-
动态字段名映射:JSON 中 key 是运行时才知的字符串(如指标名),可用
Map先解析,再通过反射设置目标对象字段 -
统一忽略空值逻辑:遍历对象所有字段,用反射判断是否为 null 或空集合,再决定是否写入 JSON(但更推荐用
@JsonInclude(Include.NON_NULL)) -
兼容旧版字段别名:如服务端返回
"usr_id",但 Java 字段是userId,可写一个反射工具根据别名映射赋值
注意:这类手动反射易出错、难调试,应优先用库原生能力(如 Jackson 的 @JsonAlias)。
常见问题与规避建议
反射引发的 JSON 异常往往源于类结构不满足库默认假设:
-
No suitable constructor found → 补无参构造,或显式注册模块(Jackson 的
SimpleModule+ 自定义StdDeserializer) -
Cannot deserialize instance… no String-argument constructor → 枚举或不可变类缺少合适构造,加
@JsonCreator标注静态工厂方法 -
Could not determine type parameter → 泛型擦除导致反序列化失败,用
TypeReference(Jackson)或TypeToken(Gson)显式传入类型 -
Access denied on private field → 某些安全策略禁用
setAccessible,可配置库启用“宽松访问”(如 Jackson 的MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS默认开启)
不复杂但容易忽略:反射是 JSON 库的“隐形引擎”,开发者只需关注模型设计与注解配置,把底层细节交给成熟库处理即可。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










