# MsgMapper **Repository Path**: ka2ka/msg-mapper ## Basic Information - **Project Name**: MsgMapper - **Description**: 这是一个适合报文转换的工具,实现不同业务到领域模型的报文映射,支持jsonPath、groovy等 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-04-08 - **Last Updated**: 2025-05-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Interface Mapper 一个轻量级的接口参数映射库,可以根据配置将业务参数映射为调用下游接口所需的参数格式。不依赖 Spring 框架,可以在任何 Java 项目中使用。 ## 功能特点 - 支持简单字段映射(A → B) - 支持表达式计算(例如:`= root.amount * 100`) - 支持引用公共配置(`@common.xxx`) - 支持默认值设置 - 支持必填字段校验 - 支持嵌套对象映射 - 支持请求和响应的双向映射 - 支持从文件加载配置 - 支持日期类型格式化 - 支持JsonPath语法获取数据 - 支持Java Bean对象映射 ## 快速开始 ### 运行示例程序 项目包含多个示例程序,展示了不同的使用场景: 1. **简单绑卡测试**:使用简单的字段映射 ``` java -cp target/interface-mapper-1.0-SNAPSHOT.jar com.interfacemapper.example.SimpleBindCardTest ``` 2. **请求映射测试**:演示A→B→C场景的参数映射 ``` java -cp target/interface-mapper-1.0-SNAPSHOT.jar com.interfacemapper.example.RequestMappingExample ``` 3. **表达式测试**:展示各种表达式用法 ``` java -cp target/interface-mapper-1.0-SNAPSHOT.jar example.com.kaka.jsonmap.FileConfigExpressionTest ``` 4. **日期格式化测试**:展示日期类型的格式化功能 ``` java -cp target/interface-mapper-1.0-SNAPSHOT.jar com.interfacemapper.example.DateFormatTest ``` 5. **JsonPath测试**:展示使用JsonPath获取嵌套数据 ``` java -cp target/interface-mapper-1.0-SNAPSHOT.jar example.com.kaka.jsonmap.JsonPathTest ``` 6. **Java Bean映射测试**:展示Java Bean对象到目标格式的映射 ``` java -cp target/interface-mapper-1.0-SNAPSHOT.jar example.com.kaka.jsonmap.BeanMappingTest ``` 运行这些示例时,程序会自动在`config`目录下创建对应的配置文件,之后您可以直接修改配置文件而无需修改代码。 ## 配置格式 配置使用 JSON 格式,包含以下主要部分: ```json { "common": { "字段名": "值或表达式" }, "interfaces": [ { "name": "接口名称", "request": { "目标字段": "源字段路径", "目标字段2": { "path": "源字段路径", "default": "默认值", "required": true|false, "value": "直接值或表达式" }, "目标字段3": "= 表达式", "目标字段4": "@common.字段名", "日期字段": { "type": "LocalDate", "format": "yyyy年MM月dd日", "field": "源日期字段名" }, "JsonPath字段": "$.嵌套.对象.字段", "复杂JsonPath": { "jsonPath": "$.items[*].name", "required": true } }, "response": { "目标字段": "源字段路径" // ... 与 request 格式相同 } } ] } ``` ## 配置文件 所有配置文件默认保存在项目根目录的`config`文件夹中: - `config/simple_bindcard.json` - 简单绑卡测试配置 - `config/request_mapping.json` - 请求映射测试配置 - `config/expression_test.json` - 表达式测试配置 - `config/date_format_test.json` - 日期格式化测试配置 - `config/jsonpath_test.json` - JsonPath测试配置 您可以直接编辑这些配置文件,然后重新运行对应的测试程序,无需修改代码。 ## 映射规则 1. **简单映射**:`"目标字段": "源字段路径"` 2. **表达式**:`"目标字段": "= 表达式"`,表达式可以使用 `root` 引用源对象 3. **引用公共配置**:`"目标字段": "@common.字段名"` 4. **日期格式化**:使用对象定义日期类型和格式 5. **JsonPath**:`"目标字段": "$.嵌套.对象.字段"` 或使用对象形式 6. **复杂映射**:使用对象定义更多规则,如默认值、必填等 ## 日期格式化 支持以下日期类型的格式化: - **LocalDate**: Java 8时间API中的日期类型 - **LocalDateTime**: Java 8时间API中的日期时间类型 - **Date**: 传统的Java日期类型 配置示例: ```json { "start_date": { "type": "LocalDate", "format": "yyyy年MM月dd日", "field": "startDate" }, "end_date": { "type": "LocalDate", "format": "yyyy/MM/dd", "field": "endDate" } } ``` ## JsonPath支持 JsonPath是一种用于从JSON对象中提取数据的查询语言,类似于XML的XPath。 ### JsonPath语法 - `$` - 根对象 - `.` - 子对象访问 - `[]` - 数组访问 - `[n]` - 访问数组的第n个元素 - `[*]` - 访问数组的所有元素 - `..` - 递归搜索 - `[?(表达式)]` - 过滤表达式 ### 配置示例 ```json { "applyId": "$.bizContext.applyId", "userName": "$.bizContext.user.name", "firstItem": "$.bizContext.items[0].name", "allItems": "$.bizContext.items[*].name", "bind_card": { "jsonPath": "$.bindCardInfo.cardNo", "required": true } } ``` ## 表达式语法说明 表达式使用JEXL引擎进行计算,语法示例: - 访问源对象:`root.fieldName`(支持嵌套路径:`root.user.address.city`) - 算术运算:`root.amount * 100` - 条件判断:`root.status == 1 ? 'Y' : 'N'` - 方法调用:`root.items.stream().mapToLong(item -> item.amt).sum()` - 默认值处理:`root.optionalField ?: defaultValue` > **注意**:当前版本暂不支持now()函数,请使用固定值替代。 ## 使用示例 ### 简单映射 配置文件 `config/request_mapping.json`: ```json { "interfaces": [ { "name": "request_mapping", "request": { "serialNo": "requestNo" } } ] } ``` Java代码: ```java // 加载配置 MappingConfig mappingConfig = ConfigurationParser.loadConfiguration("config/request_mapping.json"); MappingEngine engine = new MappingEngine(mappingConfig); // 源数据 Map source = new HashMap<>(); source.put("requestNo", "123435343453453"); // 执行映射 Map result = engine.mapRequest("request_mapping", source); // 结果: {serialNo=123435343453453} ``` ### JsonPath映射示例 配置文件 `config/jsonpath_test.json`: ```json { "interfaces": [ { "name": "jsonpath_test", "request": { "userName": "$.bizContext.user.name", "firstItem": "$.bizContext.items[0].name" } } ] } ``` Java代码: ```java // 加载配置 MappingConfig mappingConfig = ConfigurationParser.loadConfiguration("config/jsonpath_test.json"); MappingEngine engine = new MappingEngine(mappingConfig); // 源数据 - 嵌套的JSON结构 Map source = new HashMap<>(); Map bizContext = new HashMap<>(); Map user = new HashMap<>(); user.put("name", "张三"); bizContext.put("user", user); source.put("bizContext", bizContext); // 执行映射 Map result = engine.mapRequest("jsonpath_test", source); // 结果: {userName=张三} ``` ## Java Bean映射 除了支持Map对象的映射外,Interface Mapper还支持直接映射Java Bean对象。这对于与现有业务系统集成特别有用,无需手动将Bean转为Map。 ### 配置示例 ```json { "interfaces": [ { "name": "credit_apply", "request": { "apply_no": "applyNo", "product_code": "productNo", "channel_product_code": "channelProductNo", "credit_limit": "creditLimit", "repay_mode": "repayMode" } } ] } ``` ### Java代码示例 ```java // 加载配置 MappingConfig mappingConfig = ConfigurationParser.loadConfiguration("config/bean_mapping_test.json"); MappingEngine engine = new MappingEngine(mappingConfig); // 创建Bean对象 CreditApplyReq creditApplyReq = new CreditApplyReq(); creditApplyReq.setApplyNo("AP20231225001"); creditApplyReq.setProductNo("PROD001"); creditApplyReq.setChannelProductNo("CHANNEL_PROD001"); creditApplyReq.setCreditLimit(new BigDecimal("10000.00")); creditApplyReq.setRepayMode("等额本息"); // 直接映射Bean对象 Map result = engine.mapRequestBean("credit_apply", creditApplyReq); // 结果: {apply_no=AP20231225001, product_code=PROD001, ...} ``` ### 映射原理 Bean映射功能通过以下步骤工作: 1. 通过Jackson库尝试将Bean转换为Map(优先使用,可处理复杂嵌套对象) 2. 如果Jackson转换失败,则通过Java反射API获取Bean的所有getter方法并提取值 3. 将转换后的Map传递给标准的映射流程进行处理 这种方式可以无缝支持各种Java Bean对象,包括具有注解和复杂继承结构的Bean。 ## 自定义扩展 可以通过扩展 `ExpressionEvaluator` 类添加更多自定义函数,或者扩展 `MappingEngine` 类添加更多映射类型的支持。 ## Lombok优化 项目使用Lombok简化了Java Bean的编写,减少了样板代码,提高了可读性和可维护性。 ### 主要优化 1. **所有模型类**:使用`@Data`注解代替getter/setter方法 2. **FieldMapping**:使用`@Builder`模式支持更便捷的对象创建 3. **DefaultCreditApplyReq**:使用`@Accessors(chain = true)`实现链式调用 4. **更简洁的代码**:移除了大量重复的getter/setter代码 ### 示例:优化前后对比 优化前: ```java public class CreditApplyReq { private String applyNo; public String getApplyNo() { return applyNo; } public void setApplyNo(String applyNo) { this.applyNo = applyNo; } // 其他字段的getter/setter... } ``` 优化后: ```java @Data @Accessors(chain = true) public class CreditApplyReq { private String applyNo; private String productNo; // 其他字段... } ``` ### 链式调用示例 ```java // 常规方式 CreditApplyReq req1 = new CreditApplyReq(); req1.setApplyNo("AP001"); req1.setProductNo("P001"); // 链式调用方式 CreditApplyReq req2 = new CreditApplyReq() .setApplyNo("AP002") .setProductNo("P002"); ``` ### Lombok运行测试 ``` java -cp target/interface-mapper-1.0-SNAPSHOT.jar com.kaka.jsonmap.example.LombokBeanTest ``` ## Groovy 支持 该库支持使用 Groovy 表达式进行数据转换和处理。Groovy 表达式使用 `groovy()` 语法,可以在表达式中使用 Groovy 的所有特性。 ### Groovy 语法示例 ```json { "repayMode": "groovy($.bizContent.sepOutInfo[0].amt * 100)", "totalAmount": "groovy($.bizContent.sepOutInfo.collect { it.amt }.sum())", "itemCount": "groovy($.bizContent.sepOutInfo.size())", "hasLargeAmount": "groovy($.bizContent.sepOutInfo.any { it.amt > 1000 })" } ``` ### Groovy 特性 1. 集合操作 - `collect`: 转换集合元素 - `sum`: 计算集合元素总和 - `size`: 获取集合大小 - `any`: 检查是否存在满足条件的元素 2. 条件判断 - 使用 `if/else` 语句 - 使用三元运算符 `?:` - 使用 `switch` 语句 3. 字符串操作 - 字符串插值 - 正则表达式匹配 - 字符串格式化 4. 数学运算 - 基本算术运算 - 数学函数调用 - 数值转换 ### 运行 Groovy 测试示例 ```bash mvn compile exec:java -Dexec.mainClass="com.kaka.jsonmap.example.GroovyTest" ```