参数映射服务完整解决方案
参数映射服务完整解决方案
1. 背景说明
在复杂的工作流程中,后续程序需要动态构造输入参数,这些参数源自多个前序程序的 JSON 数据输出。为了增强系统的灵活性和可扩展性,需要一个通用的参数映射服务来处理这种复杂的数据转换需求。
1.1 主要挑战
- 数据来源多样性:需要处理来自不同程序的多种格式数据
- 映射逻辑复杂:包含条件判断、循环处理、多源合并等场景
- 配置驱动:需要通过配置文件定义映射规则,避免硬编码
- 扩展性要求:支持新增映射类型,保持代码结构清晰
2. 核心需求
2.1 基础功能需求
- 简单参数映射:支持从单一来源提取数据
- 复杂逻辑支持:
- 条件逻辑(if-then-else)
- 循环体处理
- 字段映射和合并
- 多来源支持:从多个前序程序提取数据,支持不同合并策略
- 常量支持:允许直接使用固定值
2.2 设计目标
- 通用性:提供统一的配置结构
- 灵活性:支持多种动态逻辑
- 易读性:配置结构清晰直观
- 可扩展性:易于添加新的映射类型
3. 系统架构
3.1 架构图
+----------------+ +----------------+ +----------------+
| 前序程序输出 | ------> | 参数映射服务 | -------> | 后序程序输入参数 |
| JSON 数据 | | (JSON 配置驱动) | | 动态生成 |
+----------------+ +----------------+ +----------------+
3.2 核心组件
- 值对象基类:定义通用接口和基础功能
- 专用值对象:实现不同类型的参数映射逻辑
- 值对象工厂:负责创建具体的值对象实例
- 参数映射服务:统一的服务入口
4. 配置结构设计
4.1 参数配置
字段名称 | 类型 | 必填 | 说明 |
---|---|---|---|
name | string | 是 | 参数名称 |
value | object | 是 | 参数值定义 |
description | string | 否 | 参数描述 |
4.2 值对象类型
4.2.1 常量值(ConstantValue)
{"type": "constant","value": "固定值"
}
4.2.2 单一来源(SingleSourceValue)
{"type": "jmespath","jmespath": "data.path.to.value"
}
4.2.3 多来源(MultiSourceValue)
{"type": "multiSource","sources": {"sourceA": "path.to.arrayA","sourceB": "path.to.arrayB"},"mergeStrategy": "concat"
}
4.2.4 循环体(LoopValue)
{"type": "loop","jmespath": "items[*]","mappings": {"id": "id","name": "name"}
}
4.2.5 条件值(ConditionalValue)
{"type": "conditional","jmespath": "status","conditions": [{"if": "status == 'success'","then": {"type": "constant","value": "成功"}}],"else": {"type": "constant","value": "其他"}
}
5. 代码实现
5.1 工具函数
import jp from "jmespath";/*** 安全的 JMESPath 查询* @param {Object} data - 查询的上下文对象* @param {string} expression - JMESPath 表达式* @param {*} defaultValue - 查询失败时的默认值* @returns {*} 查询结果或默认值*/
function safeJMESPath(data, expression, defaultValue = null) {try {const result = jp.search(data, expression);return result !== undefined ? result : defaultValue;} catch (error) {console.warn(`JMESPath 查询失败: ${expression}`, error);return defaultValue;}
}
5.2 值对象基类
/*** 值对象基类*/
class ValueObject {constructor(config) {this.type = config.type;if (!this.type) {throw new Error("值对象类型未定义");}}getValue(context) {throw new Error("子类必须实现 getValue 方法");}
}
5.3 专用值对象实现
/*** 常量值对象*/
class ConstantValue extends ValueObject {constructor(config) {super(config);this.value = config.value;if (this.value === undefined) {throw new Error("常量值未指定");}}getValue() {return this.value;}
}/*** 单一来源值对象*/
class SingleSourceValue extends ValueObject {constructor(config) {super(config);this.jmespath = config.jmespath;if (!this.jmespath) {throw new Error("JMESPath 表达式未指定");}}getValue(context) {return safeJMESPath(context, this.jmespath);}
}/*** 多来源值对象*/
class MultiSourceValue extends ValueObject {constructor(config) {super(config);this.sources = config.sources;this.mergeStrategy = config.mergeStrategy || "concat";if (!this.sources || typeof this.sources !== "object") {throw new Error("多来源配置无效");}}getValue(context) {const values = Object.entries(this.sources).map(([key, jmespath]) => {return safeJMESPath(context[key], jmespath, []);});switch (this.mergeStrategy) {case "concat":return values.flat();case "unique":return [...new Set(values.flat())];case "priority":return values.find((value) => value.length > 0) || [];default:throw new Error(`不支持的合并策略: ${this.mergeStrategy}`);}}
}/*** 循环体值对象*/
class LoopValue extends ValueObject {constructor(config) {super(config);this.jmespath = config.jmespath;this.mappings = config.mappings || {};if (!this.jmespath) {throw new Error("循环体数据源表达式未指定");}}getValue(context) {const array = safeJMESPath(context, this.jmespath, []);if (!Array.isArray(array)) {return [];}return array.map((item) => {const mappedItem = {};for (const [key, expression] of Object.entries(this.mappings)) {mappedItem[key] = safeJMESPath(item, expression);}return mappedItem;});}
}/*** 条件值对象*/
class ConditionalValue extends ValueObject {constructor(config) {super(config);this.jmespath = config.jmespath;this.conditions = config.conditions || [];this.else = config.else;if (!this.jmespath) {throw new Error("条件数据源表达式未指定");}}getValue(context) {const data = safeJMESPath(context, this.jmespath, {});for (const condition of this.conditions) {if (safeJMESPath(data, condition.if, false)) {return new ValueObjectFactory().create(condition.then).getValue(context);}}return this.else ? new ValueObjectFactory().create(this.else).getValue(context) : null;}
}
5.4 值对象工厂
/*** 值对象工厂*/
class ValueObjectFactory {constructor() {this.typeMap = {constant: ConstantValue,jmespath: SingleSourceValue,multiSource: MultiSourceValue,loop: LoopValue,conditional: ConditionalValue,};}create(config) {const ValueObjectClass = this.typeMap[config.type];if (!ValueObjectClass) {throw new Error(`不支持的值对象类型: ${config.type}`);}return new ValueObjectClass(config);}
}
5.5 参数映射服务
/*** 参数映射服务*/
class ParameterMappingService {constructor(config) {this.parameters = config.parameters || [];this.factory = new ValueObjectFactory();}mapParameters(context) {const output = {};for (const param of this.parameters) {try {const valueObject = this.factory.create(param.value);output[param.name] = valueObject.getValue(context);} catch (error) {console.error(`处理参数 ${param.name} 时发生错误:`, error);output[param.name] = null;}}return output;}
}
6. 使用示例
// 配置示例
const config = {parameters: [{name: "version",value: {type: "constant",value: "1.0.0"}},{name: "userId",value: {type: "jmespath",jmespath: "userInfo.id"}},{name: "permissions",value: {type: "multiSource",sources: {rolePerms: "permissions[*].code",userPerms: "customPermissions[*]"},mergeStrategy: "unique"}}]
};// 示例数据
const context = {userInfo: {id: "user123"},rolePerms: {permissions: [{ code: "READ" },{ code: "WRITE" }]},userPerms: {customPermissions: ["ADMIN"]}
};// 使用示例
const service = new ParameterMappingService(config);
const result = service.mapParameters(context);
console.log(result);
/* 输出:
{version: "1.0.0",userId: "user123",permissions: ["READ", "WRITE", "ADMIN"]
}
*/
7. 总结
本解决方案通过灵活的配置结构和可扩展的代码设计,实现了一个通用的参数映射服务。主要特点:
- 配置驱动:通过 JSON 配置文件定义映射规则
- 类型丰富:支持常量、单源、多源、循环、条件等多种映射类型
- 扩展性好:基于工厂模式,易于添加新的值对象类型
- 健壮性强:完善的错误处理和默认值机制
后续优化方向
- 支持更多合并策略
- 添加参数验证功能
- 支持自定义函数扩展
- 增加缓存机制
- 添加映射性能监控