Search code examples
dataweavemulesoft

Mule DataWeave How to merge header and lines in json


Need to merge header with lines in generic manner. Header and lines before the next header belongs to one object . For one header_n there can be many lines_n .
example header_0 and line_1 and line_2 are one object. For one Header_n there can be many Line before we find another header.

Input:

[
  {
    "Header_0": {
      "Recordtype": "1"
   
    }
  },
  {
    "lines_1": {
      "RecordType": "2"
 
    }
  },
  {
    "lines_2": {
      "RecordType": "2"
      
    }
  },
  {
    "Header_3": {
      "Recordtype": "1"
     
     
    }
  },
  {
    "lines_4": {
      "RecordType": "2"
  
    
    }
  },
  {
    "lines_5": {
      "RecordType": "2"

   
    }
  },
  {
    "lines_6": {
      "RecordType": "2"
     
  
    }
  },
  {
    "lines_7": {
      "RecordType": "2"
   
            }
  }
]

Output:

[
    {
        "Header_0": {
            "Recordtype": "1",
            "LineItems": [
                {
                    "lines_1": {
                        "RecordType": "2"
                    }
                },
                {
                    "lines_2": {
                        "RecordType": "2"
                    }
                }
            ]
        }
    },
    {
        "Header_3": {
            "Recordtype": "1",
            "LineItems": [
                {
                    "lines_4": {
                        "RecordType": "2"
                    }
                },
                {
                    "lines_5": {
                        "RecordType": "2"
                    }
                },
                {
                    "lines_6": {
                        "RecordType": "2"
                    }
                },
                {
                    "lines_7": {
                        "RecordType": "2"
                    }
                }
            ]
        }
    }
]
 

If not possible in Dataweave, let me know what other option we can try in mule.


Solution

  • You can use the following DataWeave

    It basically loops through the input array, adds the "Header" records to the output array accumulator and adds the subsequent "Lines" to the last added header in the output array

    %dw 2.0
    import update, index from dw::util::Values
    output application/json
    
    fun isHeader(record) = record..Recordtype[0] == "1"
    
    fun addLineItemToHeader(headerRecord, lineItemRecord) = 
        headerRecord  update {
            case .LineItems! -> ($ default []) << lineItemRecord
        }
    
    ---
    payload reduce ((item, acc = []) -> 
        if(isHeader(item)) acc << item
        else acc update index(sizeOf(acc)-1) 
            with ($ addLineItemToHeader item)
    )