Home > Software design >  DataWeave JSON Transformation/ Extract and concatenate values
DataWeave JSON Transformation/ Extract and concatenate values

Time:04-27

I'm looking to go from a JSON structure that looks something like this:

{
  "id": "955559665",
  "timestamp": "2022-04-21 00:00:19",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Safari/605.1.15",
  "remote_addr": "123.456.789.012",
  "read": "0",
  "data": {
      "80928111": {
          "field": "80928111",
          "value": "Z01234567",
          "flat_value": "Z01234567",
          "label": "ID",
          "type": "text"
      },
      "90924321": {
          "field": "90924321",
            "value": {
                "first": "Jane",
                "last": "Doe"
            },
            "flat_value": "first = Jane\nlast = Doe",
            "label": "Name",
            "type": "name"
        },
        "88888770": {
            "field": "88888770",
            "value": "[email protected]",
            "flat_value": "[email protected]",
            "label": "Email",
            "type": "email"
        },
        "12345678": {
            "field": "12345678",
            "value": "https://www.google.com/subdomain/attachment/file.txt",
            "flat_value": "https://www.google.com/subdomain/attachment/file.txt",
            "label": "Choose File",
            "type": "file"
        }
    }
}

Ultimately to something like this:

{
    "name_val":"Name: first = Jane\nlast = Doe\nEmail: [email protected]\n",
    "file": {
      "id": "12345678C",
      "name": "file.txt"
    }
}

In the original JSON, the 'data' object represents a form submission. Each sub object represents a field on the submitted form. The only distinction I'm interested in is the 'type' of field identified as 'file'.

Every response that is not of 'file' type, I want to concatenate into one large String value that looks like: 'label1: flat_value1\nlabel2: flat_value2...'

Note, the number of actual fields is variable.

Then I need a second object to show the field of type 'file', by identifying the 'field' id, and the name of the file.

I've gotten pieces of this to work. For example, using pluck and filter, I've been able to separate the types of fields.

Something like this:

%dw 2.0
output application/json
---
[
    "fields": payload.data pluck(
        {
            "field": $."label",
            "value": $."flat_value",
            "type": $."type"
        }
    ) filter ($."type" != "file") default "",
    "files": payload.data pluck(
        {
            "type": $."type",
            "fieldId": $."field"
        }
    ) filter ($."type" == "file") default ""
]

Gives me:

[
  {
    "fields": [
      {
        "field": "ID",
        "value": "Z01234567",
        "type": "text"
      },
      {
        "field": "Name",
        "value": "first = Jane\nlast = Doe",
        "type": "name"
      },
      {
        "field": "Email",
        "value": "[email protected]",
        "type": "email"
      }
    ]
  },
  {
    "files": [
      {
        "type": "file",
        "fieldId": "12345678"
      }
    ]
  }
]

And playing around with a modified JSON input, I was able to easily see concatenation similar to how I want to see it, but not quite there:

%dw 2.0
output application/json
var inputJson = [
    {
        "field": "ID",
        "value": "Z01234567",
        "type": "text"
    },
    {
        "field": "Name",
        "value": "first = Jane\nlast = Doe",
        "type": "name"
    }
]
---


inputJson map ((value, index) -> value.field    ': '    value.value)

Gives me:

[
  "ID: Z01234567",
  "Name: first = Jane\nlast = Doe"
]

But I can't seem to put it all together and go from Beginning to End.

CodePudding user response:

There are several ways to implement this. I recommend to try to encapsulate the parts that you get working and use them as building blocks.

%dw 2.0
output application/json
fun fields(x) = x.data pluck(
        {
            "field": $."label",
            "value": $."flat_value",
            "type": $."type"
        }
    ) filter ($."type" != "file") default ""
fun files(x) = x.data pluck(
        {
            "type": $."type",
            "fieldId": $."field"
        }
    ) filter ($."type" == "file") default ""
---
{
    name_val: fields(payload) reduce ((item,acc="") -> acc    item.field    ': '    item.value    "\n"),
    files: files(payload)[0]
}

Output:

{
  "name_val": "ID: Z01234567\nName: first = Jane\nlast = Doe\nEmail: [email protected]\n",
  "files": {
    "type": "file",
    "fieldId": "12345678"
  }
}
  • Related