将多部分格式数据转换为嵌套 JSON

问题描述 投票:0回答:1

我正在尝试将多部分格式数据动态转换为 JSON

输入数据

----------------------------439270980986078404603032
Content-Disposition: form-data; name="key1"

value1
----------------------------439270980986078404603032
Content-Disposition: form-data; name="key2[name]"

name
----------------------------439270980986078404603032
Content-Disposition: form-data; name="key2[phone]"

phone
----------------------------439270980986078404603032
Content-Disposition: form-data; name="key2[location]"


----------------------------439270980986078404603032
Content-Disposition: form-data; name="key2[vaid]"

true
----------------------------439270980986078404603032
Content-Disposition: form-data; name="key3"


----------------------------439270980986078404603032
Content-Disposition: form-data; name="key4"

value4
----------------------------439270980986078404603032
Content-Disposition: form-data; name="key2[address][city]"

xyz
----------------------------439270980986078404603032
Content-Disposition: form-data; name="key2[address][state]"

abc
----------------------------439270980986078404603032
Content-Disposition: form-data; name="key2[address][code]"

5678
----------------------------439270980986078404603032
Content-Disposition: form-data; name="key2[address][country]"

US
----------------------------439270980986078404603032--

预期产出

{
    "key1": "value1",
    "key2": {
        "name": "name",
        "phone": "phone",
        "location": null,
        "valid": true,
        "address": {
            "city": "xyz",
            "state": "abc",
            "code": 5678,
            "country": "US"
        }
    },
    "key3": null,
    "key4": "value4"

}

我试过的DataWeave

%dw 2.0
output application/json
---
{
    "key1": payload.parts.key1.content,
    "key2": {
        "name": payload.parts."key2[name]".content,
        "phone": payload.parts."key2[phone]".content,
        "location": payload.parts."key2[location]".content,
        "valid": payload.parts."key2[vaid]".content,
        "address": {
            "city": payload.parts."key2[address][city]".content,
            "state": payload.parts."key2[address][state]".content,
            "code": payload.parts."key2[address][code]".content,
            "country": payload.parts."key2[address][country]".content
        }
    },
    "key3": payload.parts.key3.content,
    "key4": payload.parts.key4.content
}

上面的 DataWeave 虽然给出了预期的输出,但它不适用于所有类型的场景,比如我们从有效负载中添加或删除密钥。就我而言,动态解决方案更可取。例如,还有一个场景,其中

name = key2[address][state][county]
也需要动态处理。

mule dataweave
1个回答
1
投票

这个问题有两个部分:将多部分输入转换为可用于转换的东西,并在输出 JSON 之前将具有子索引表达式的中间结果转换为嵌套对象。第二部分是困难的,但幸运的是之前已经问过并且已经有关于如何做到这一点的先前答案

对于第一部分,我将只获取多部分的部分并丢弃其他所有内容:

payload.parts 
    mapObject ((value, key, index) -> (key): value.content)

然后我将重复使用以前的答案,该答案从格式为

"abc.def.ghi"
的键创建嵌套对象。因为这个问题使用格式为
"key2[address][city]"
的键,所以我使用了一个小的实用函数来用键名中的点替换大括号的组合:

fun convertKeys(s)=s replace "][" with "." replace "[" with "." replace "]" with "."    

完整的剧本是:

%dw 2.0
output application/json
import * from dw::util::Values

fun upsert(object: {}, path:Array<String>, value: Any): Object = do {
    path match {
        case [] -> object
        case [x ~ xs] -> 
                if(isEmpty(xs))
                    object update  {
                        case ."$(x)"! -> value                                
                    }
                else
                    object update  {
                        case selected at ."$(x)"! -> 
                            //selected is going to be null when the value is not present  
                            upsert(selected default {}, xs, value)
                    }  
    }
}

fun groupSubelements(x)=x pluck ((value, key, index) -> {key: key, value: value})
    reduce ((item, resultObject = {} ) -> do {
        upsert(resultObject, (item.key as String splitBy '.') , item.value)
    })

fun convertKeys(s)=s replace "][" with "." replace "[" with "." replace "]" with "."    
---
groupSubelements(payload.parts 
    mapObject ((value, key, index) -> (convertKeys(key as String)): value.content))

输出:

{
  "key1": "value1",
  "key2": {
    "name": "name",
    "phone": "phone",
    "location": "",
    "vaid": "true",
    "address": {
      "city": "xyz",
      "state": "5678",
      "country": "US"
    }
  },
  "key3": "",
  "key4": "value4"
}

为空的部分内容作为空字符串返回。这就是 DataWeave 处理这些条目的方式。您的预期输出是将它们设为空。如果需要,您可以更改表达式

value.content
以添加空检查并返回 null:
if (isEmpty(value.content)) null else value.content

© www.soinside.com 2019 - 2024. All rights reserved.