Introduction
DataWeave comes with map, mapOjbect, pluck, and other build in functions. The map function is mostly used in the message transformation. There are a lot of other functions provided by the Dataweave component, such as split, trim, uppercase, lower case, etc.
This tutorial is an example on how to use map, mapObject, plunk, and joinBy functions to achieve a fairly complicated message transformation.
Use Cases
Input Data
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | < soapenv:envelope xmlns:ns = "http://taxi.uhc.com/1.0" xmlns:soapenv = "http://schemas.xmlsoap.org/soap/envelope/" > < soapenv:header > < soapenv:body > < ns:preauth > < ns:ssi >venkat</ ns:ssi > < ns:custid >api-user-jwilson</ ns:custid > < ns:password >4JuGSrVb1E7k8a1datKuGV0fqma58c2B</ ns:password > < ns:billingid >VC84632147254611111111</ ns:billingid > < ns:amount >5000</ ns:amount > < ns:personal-info > < ns:name >John Smith</ ns:name > < ns:address1 >12 Main St</ ns:address1 > < ns:address2 >Raheja</ ns:address2 > < ns:zip >30301</ ns:zip > < ns:city >Denver</ ns:city > < ns:state >CO</ ns:state > < ns:country >USA</ ns:country > < ns:phone >6099026676</ ns:phone > < ns:email >gg@gmail.com</ ns:email > < ns:ip >10.121.123.112</ ns:ip > </ ns:personal-info > < ns:ship-info > < ns:shipto_name >John Smith</ ns:shipto_name > < ns:shipto_address1 >12 Main St</ ns:shipto_address1 > < ns:shipto_address2 >SR Nagar</ ns:shipto_address2 > < ns:shipto_zip >30301</ ns:shipto_zip > < ns:shipto_city >Denver</ ns:shipto_city > < ns:shipto_state >CO</ ns:shipto_state > < ns:shipto_country >USA</ ns:shipto_country > </ ns:ship-info > < ns:optional-info > < ns:cvv >111</ ns:cvv > < ns:avs >false</ ns:avs > < ns:ticket >V12345</ ns:ticket > < ns:type >MOTO</ ns:type > < ns:iias_lookup >true</ ns:iias_lookup > < ns:partialauth >true</ ns:partialauth > < ns:marketindicator >H</ ns:marketindicator > < ns:additionalamount1 >3000</ ns:additionalamount1 > < ns:additionalamount2 >1000</ ns:additionalamount2 > < ns:demo >false</ ns:demo > < ns:level-2-3-fields > < ns:level-2-field > < ns:numitems >1</ ns:numitems > < ns:purchaselevel >1</ ns:purchaselevel > < ns:purchaseordernum >T1234522</ ns:purchaseordernum > < ns:tax >100</ ns:tax > < ns:taxidentifier >localsales</ ns:taxidentifier > < ns:vatnum >A10004</ ns:vatnum > < ns:commoditycode >AA01</ ns:commoditycode > < ns:discount >100</ ns:discount > < ns:duty >400</ ns:duty > < ns:shippinghandling >300</ ns:shippinghandling > </ ns:level-2-field > < ns:level-3-field > < ns:productcode >02</ ns:productcode > < ns:quantity >1</ ns:quantity > < ns:price >120</ ns:price > < ns:tax >120</ ns:tax > < ns:discount >30</ ns:discount > < ns:productdescription >t-shirt</ ns:productdescription > < ns:unitofmeasure >each</ ns:unitofmeasure > < ns:taxamount >300</ ns:taxamount > < ns:taxidentifier >0001</ ns:taxidentifier > </ ns:level-3-field > < ns:level-3-field > < ns:productcode >001</ ns:productcode > < ns:quantity >1</ ns:quantity > < ns:price >120</ ns:price > < ns:tax >120</ ns:tax > < ns:discount >30</ ns:discount > < ns:productdescription >t-shirt</ ns:productdescription > < ns:unitofmeasure >each</ ns:unitofmeasure > < ns:taxamount >300</ ns:taxamount > < ns:taxidentifier >0001</ ns:taxidentifier > </ ns:level-3-field > </ ns:level-2-3-fields > < ns:custom-fields > < ns:custom-field sequence = "7" value = "venkat" > </ ns:custom-field ></ ns:custom-fields > </ ns:optional-info > </ ns:preauth > </ soapenv:body > </ soapenv:header ></ soapenv:envelope > |
Output
1 2 3 | { "result" : "(productcode=02;quantity=1;price=120;tax=120;discount=30;productdescription=t-shirt;unitofmeasure=each;taxamount=300;taxidentifier=0001)(productcode=001;quantity=1;price=120;tax=120;discount=30;productdescription=t-shirt;unitofmeasure=each;taxamount=300;taxidentifier=0001)" } |
We need to create key-value pairs for level-e-field. Each key-value pair is separated by semi-colon, and each object is demarked by round braket. (key1=value1;key2=value2;...;keyN=valueN)().
The Solution
1 2 3 4 5 6 7 8 9 10 11 | %dw 1.0 %output application/json % function enrich(val) '(' ++ val ++ ')' --- result: payload.Envelope.Body.preauth.optional-info.level-2-3-fields.*level-3-field map ((value,index) -> ( value mapObject ((oValue, oKey) -> { '$oKey' : oKey ++ '=' ++ oValue }) pluck $ joinBy ';' )) map ((val, key) -> enrich(val)) joinBy '' |
The first code line 5 is easy to understand. We need to access the xml object at level-3-file. The only trick we need to know is that we need to add a star *. As we have multiple level-3-field object, we need to use map. map function is just a look. It takes two parameters. The first is value of the object, and the second is the index. If you have an array or list, you can think the first is the value of the array and the second is the index, which starts with 0 as java array.
In our code, we use twice joinBy function. The first joins the array with ';' semi-colon. The second join the level-3-field objects together.
pluck is another function which create an array of keys or values. The value is $, and the keys are $$.