0
votes

I have an input payload that I need to pass through directly to the output except for specific date attributes which I need to transform. These date attributes can be anywhere within the payload. i.e.,

  1. as key/value pairs
  2. as key/value pairs within an object
  3. as key/value pairs within an array
  4. as key/value pairs within an object in an array

I have addressed cases 1 and 2 above with the dataweave code below. However, I am a little stuck with cases 3 and 4. Would very much appreciate any pointers in this regard. Thanks!

Input payload:

{
   "key1":"value1",
   "key2":"value2",
   "arrayList1":[
      {
         "key3":"value3",
         "datefield_1":"13/01/2006",
         "datefield_2":"15/06/1980",
         "arrayList2":[
            {
               "key4":"value4",
               "datefield_3":"13/01/2000",
               "datefield_4":"15/06/2003",
               "arrayList2":[
                  {
                     "key5":"value5",
                     "datefield_5":"30/01/2000",
                     "datefield_6":"14/06/2003"
                  }
               ]
            }
         ]
      },
      {
         "key6":"value6",
         "datefield_7":"20/02/2000"
      }
   ]
}

Dataweave code:

%dw 1.0
 %output application/json
 %var keysToUpdate = ['datefield_1', 'datefield_2', 'datefield_3', 'datefield_4', 'datefield_5', 'datefield_6', 'datefield_7']
 %function transformDateFormat(inputDate) inputDate as :date {format: "dd/MM/yyyy"} as :date {format: "yyyy-MM-dd"}
 %function findKey(key) keysToUpdate contains key
 %function changePayload(input) input mapObject ({
     ($$): changePayload($) when $ is :object otherwise $
     } unless findKey($$ as :string) otherwise {
     ($$): transformDateFormat($)
 })
 ---
 changePayload (payload)  
1

1 Answers

1
votes

The match operator with some recursion will be helpful here.

Try this out. I created a function, applyToValuesWhenKey, that takes in the input value as e, a function to apply to the values as fn, and a function that returns a boolean that will dictate whether or not to apply fn to the value called predicate. It uses recursion and the match operator to loop through the data, applying map, mapObject, or just returning the given value depending on whether or not the current value is an object, array, or anything else. The rest is your code:

%dw 1.0
%output application/json

%var input = {
   "key1":"value1",
   "key2":"value2",
   "arrayList1":[
      {
         "key3":"value3",
         "datefield_1":"13/01/2006",
         "datefield_2":"15/06/1980",
         "arrayList2":[
            {
               "key4":"value4",
               "datefield_3":"13/01/2000",
               "datefield_4":"15/06/2003",
               "arrayList2":[
                  {
                     "key5":"value5",
                     "datefield_5":"30/01/2000",
                     "datefield_6":"14/06/2003"
                  }
               ]
            }
         ]
      },
      {
         "key6":"value6",
         "datefield_7":"20/02/2000"
      }
   ]
}

%var keysToUpdate = [ 'datefield_1', 'datefield_2', 'datefield_3', 'datefield_4', 'datefield_5', 'datefield_6', 'datefield_7' ]

%function applyToValuesWhenKey( e, fn, predicate )
  e match {
    :array  -> $ map applyToValuesWhenKey( $, fn, predicate ),
    :object -> $ mapObject ( ( v, k ) -> { 
                             ( k ): fn( v )
                           } when predicate( k ) otherwise {
                             ( k ): applyToValuesWhenKey( v, fn, predicate )
                           }
                         ),
    default -> $
  }

%function transformDateFormat( date ) 
  date as :date { format: "dd/MM/yyyy" } as :date { format: "yyyy-MM-dd" }

%function transformDates( input )
  applyToValuesWhenKey( input, 
                        transformDateFormat,
                        ( ( key ) -> keysToUpdate contains ( key as :string ) ) )
---
transformDates( input )