如何利用JSON映射文件实现Java不同POJO对象之间的自动转换
实现方案
首先修正映射文件的笔误,你提供的mapping.json里存在无效映射项:
// 错误项,没有对应的字段 { "userColumn": "last_first", "personColumn": "first_last" } // 修正为 { "userColumn": "name_last", "personColumn": "last_name" }
步骤1:预加载映射配置
在Utility类中静态加载mapping.json,只需要初始化一次,避免每次转换重复读取文件:
import com.google.gson.Gson; import java.io.IOException; import java.io.InputStreamReader; import java.lang.reflect.Method; import java.util.ArrayList; public class Utility { // 静态缓存映射配置,项目启动时加载一次即可 private static Mapping MAPPING_CONFIG; static { try (InputStreamReader reader = new InputStreamReader( Utility.class.getClassLoader().getResourceAsStream("mapping.json") )) { MAPPING_CONFIG = new Gson().fromJson(reader, Mapping.class); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException("映射配置文件加载失败", e); } } }
步骤2:实现反射调用的通用方法
封装两个通用工具方法,分别用于调用对象的getter取值、调用对象的setter赋值:
// 通用getter调用:根据字段名从目标对象取属性值 private static Object getFieldValue(Object obj, String fieldName) throws Exception { // POJO getter规则:get + 字段首字母大写 + 剩余部分 String getterName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); Method getter = obj.getClass().getMethod(getterName); return getter.invoke(obj); } // 通用setter调用:根据字段名给目标对象设属性值 private static void setFieldValue(Object obj, String fieldName, Object value) throws Exception { if (value == null) return; // 空值跳过赋值,可根据需求调整 // 先获取值的类型,作为setter的入参类型 Class<?> paramType = value.getClass(); // POJO setter规则:set + 字段首字母大写 + 剩余部分 String setterName = "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); Method setter = obj.getClass().getMethod(setterName, paramType); setter.invoke(obj, value); }
步骤3:实现动态转换逻辑
遍历预加载的映射配置,逐个完成字段的取值、赋值:
public static Person userToPerson(User u) { Person person = new Person(); ArrayList<Pair> columnMap = MAPPING_CONFIG.getColumnMap(); for (Pair pair : columnMap) { try { // 从User对象取对应字段的值 Object value = getFieldValue(u, pair.getUserColumn()); // 给Person对象对应字段赋值 setFieldValue(person, pair.getPersonColumn(), value); } catch (Exception e) { // 单个字段映射失败打日志即可,不中断整个转换,可根据业务需求调整处理逻辑 System.out.printf("字段映射失败:userColumn=%s, personColumn=%s,错误信息:%s%n", pair.getUserColumn(), pair.getPersonColumn(), e.getMessage()); } } return person; }
优化建议
- 如果需要支持基础类型(比如int、long而非包装类),可以在
setFieldValue方法里增加类型兼容判断,自动处理包装类和基础类型的匹配 - 如果需要实现Person转User的反向转换,只需要调整get和set的对象,复用同一套映射规则即可
- 生产环境可以把异常捕获替换为日志框架输出,不要直接打印控制台
- 可以把字段的getter/setter方法缓存起来,避免每次转换都反射查找方法,提升性能
内容的提问来源于stack exchange,提问作者user1068636
相关产品推荐
相关产品推荐

