动态将Multipart格式数据转换为嵌套JSON的DataWeave实现需求
动态将Multipart表单数据转换为嵌套JSON的DataWeave解决方案
核心思路
通过解析表单键的层级路径(如key2[address][state][county]拆分为["key2", "address", "state", "county"]),递归构建嵌套对象,实现完全动态适配——不管键的数量、层级深度如何变化,都无需修改代码。
示例输入(Multipart表单数据结构)
{ "key1": "value1", "key2[address][city]": "New York", "key2[address][state][county]": "New York County", "key2[phone]": "1234567890" }
期望输出
{ "key1": "value1", "key2": { "address": { "city": "New York", "state": { "county": "New York County" } }, "phone": "1234567890" } }
通用DataWeave代码
%dw 2.0 output application/json // 解析带方括号的表单键为层级路径数组 fun parseKey(key: String): Array<String> = key splitBy /\[|\]/ filter ($ != "") // 递归构建嵌套对象,自动创建不存在的层级 fun buildNested(path: Array<String>, value: Any, target: Object = {}): Object = if (sizeOf(path) == 1) target ++ {(path[0]): value} else { val currentKey = path[0] val remainingPath = path[1 to -1] val existingNode = target[currentKey] default {} target ++ {(currentKey): buildNested(remainingPath, value, existingNode)} } // 遍历所有键值对,逐步构建完整嵌套JSON --- payload reduce ((entry, acc = {}) -> buildNested(parseKey(entry.key), entry.value, acc) )
代码说明
parseKey函数:通过正则拆分键字符串,过滤空值后得到层级路径数组。例如key2[address][state][county]会被处理为["key2", "address", "state", "county"]。buildNested递归函数:- 如果路径只剩最后一个键,直接将值赋值给该键并合并到目标对象。
- 如果还有多层路径,先获取当前键对应的已有节点(不存在则新建空对象),再递归处理剩余路径,最后将更新后的节点合并回目标对象。
- 主逻辑:用
reduce遍历输入的所有键值对,逐个将键值对的路径和值构建到累加对象中,最终生成完整的嵌套JSON。
扩展支持数组类型键(可选)
如果需要处理类似key3[0][name]的数组式键,可以修改parseKey和buildNested函数,判断路径元素是否为数字来创建数组:
// 扩展解析函数,区分数组索引 fun parseKey(key: String): Array<Any> = key splitBy /\[|\]/ filter ($ != "") map ((item) -> if (item matches /^\d+$/) item as Number else item ) // 扩展递归函数,支持数组层级 fun buildNested(path: Array<Any>, value: Any, target: Any = {}): Any = if (sizeOf(path) == 1) { if (path[0] is Number) { (target default []) update path[0] with value } else { (target default {}) ++ {(path[0]): value} } } else { val currentKey = path[0] val remainingPath = path[1 to -1] val existingNode = if (currentKey is Number) (target default [])[currentKey] default {} else (target default {})[currentKey] default {} val updatedNode = buildNested(remainingPath, value, existingNode) if (currentKey is Number) { (target default []) update currentKey with updatedNode } else { (target default {}) ++ {(currentKey): updatedNode} } }
内容的提问来源于stack exchange,提问作者Karthik
相关产品推荐
相关产品推荐

