How to convert string to array and object in mule 4

305 views Asked by At

I have a requirement where I need to convert a String to array or object if present in payload or else return the value as string or boolean.

Input

{
    "Id": {
        "EmpId": 1
    },
    "employee": [
        {
            "Headers": 1234,
            "Present": true,
            "UseBa": null,
            "EmployeeNames": "[\n  'abc'\n]",
            "ClientID": "31d00",
            "types": "{\n  type: 'hello',\n  scope: 'world'\n}",
            "Request": false
        },
        {
            "Headers": 2345,
            "Present": true,
            "UseBa": null,
            "EmployeeNames": "[\n  'xyz'\n]",
            "ClientID": "31d00",
            "types": "{\n  type: 'hello',\n  scope: 'world'\n}",
            "Request": false
        }
    ]
}

I want to achieve the above output how to read and replace it.. I tried multiple things but it is not working, Please help me on this.

I tried logic

%dw 2.0
output application/json

var items = payload mapObject ((value, key, index) -> 
  (key): 
    if (typeOf(value) == String)
      (if (((value contains ("[\n")) or (value contains ("["))) and ((value contains ("\n]")) or (value contains ("["))))
        (read(value))
      else
        (value))
    else
      (value)
)
---
{
    "Id": {
        "EmpId": payload.Id.EmpId default null
    },
    "results": items
}

Above logic is not working.. please help where am going wrong

Expecting output

{
    "Id": {
        "EmpId": 1
    },
    "employee": [
        {
            "Headers": 1234,
            "Present": true,
            "UseBa": null
            "EmployeeNames": [
            "abc"
            ],
            "ClientID": "31d00",
            "types": {
            "type": "hello",
            "scope": "world"
            },
            "Request": false
        },
        {
            "Headers": 2345,
            "Present": true,
            "UseBa": null
            "EmployeeNames": [
            "xyz",
            "123"
            ],
            "ClientID": "31d00",
            "types": {
            "type": "hello",
            "scope": "world"
            },
            "Request": false
                }
    ]
}
1

There are 1 answers

2
aled On

That's because those strings contain something that looks like similar to JSON but it is not a supported format in DataWeave, even after considering the escaping. DataWeave can not parse those strings as objects because of that.

If you can change how the input is generated, then ensure that those strings are escaped JSON so they are compatible with DataWeave.

Example escaped JSON strings:

"EmployeeNames": "[\n  \"abc\"\n]",
...
"types": "{\n  \"type\": \"hello\",\n  \"scope\": \"world\"\n}",

Once the compatibility is resolved, then the conversion can be done with a recursive function which depending on the data type performs the conversion. Instead of using ifs it is more elegant to just try if the string can be read as a JSON using the try() function from the Runtime module. The ifs are much more error prone since there may be no guarantee that one of those characters are going to be included in the strings but the entire string may no be parseable, and there is no error handling in your version. Using try() prevents a failure to parse to break the script. It is not perfect but handles better the errors. In addition to objects and strings the script needs to consider arrays, applying the recursion to each element of them.

%dw 2.0
output application/json
import * from dw::Runtime

fun stringsToObjects(x)=
    x match {
        case o is Object -> o mapObject ((value, key, index) -> (key): stringsToObjects(value))
        case a is Array -> a map stringsToObjects($)
        case s is String -> 
        try(() -> 
            read(s,"application/json")) orElse s
        else -> x
    }
---
stringsToObjects(payload)

Remember to never use read() without specifying a format type as the second argument. By default it will use application/dw which is only meant to be used for debugging and should not be used in production applications.