0

Problem with using mapObject function properly. Trying to retain existing array structure but calculate number of vehicles and properties and update the existing array that contains the value. GENERAL data comes from one source, VEHICLE data comes from another source, PROPERTY data comes from another source. So when merging, I have to update GENERAL data with count of other source data. Also GENERAL is an array object, it will always have 1. So using GENERAL[0] is safe and fine.

Original Payload

[
  {
    "commId": "1",
    "GENERAL": [
      {
        "ID": "G1",
        "VEHICLE_COUNT": "TODO",
        "PROPERTY_COUNT": "TODO"
      }
    ],
    "VEHICLE": [
      {
        "ID": "V1-1"
      },
      {
        "ID": "V1-2"
      }
    ],
    "PROPERTY": [
      {
        "ID": "P1-1"
      }
    ]
  },
  {
    "commId": "2",
    "GENERAL": [
      {
        "ID": "G2",
        "VEHICLE_COUNT": "TODO",
        "PROPERTY_COUNT": "TODO"
      }
    ],
    "VEHICLE": [
      {
        "ID": "V2-1"
      }
    ],
    "PROPERTY": [
      {
        "ID": "P2-1"
      },
      {
        "ID": "P2-2"
      }
    ]
  },
  {
    "commId": "3",
    "GENERAL": [
      {
        "ID": "G3",
        "VEHICLE_COUNT": "TODO",
        "PROPERTY_COUNT": "TODO"
      }
    ],
    "VEHICLE": [
      {
        "ID": "V3-1"
      },
      {
        "ID": "V3-2"
      },
      {
        "ID": "V3-3"
      }
    ]
  }
]

Tried using map to loop through the payload and tried modifying 2 attribute but only managed to map one but even that is showing wrong output.

test map (item, index) -> {
    (item.GENERAL[0] mapObject (value, key) -> { 
        (key): (value == sizeOf (item.VEHICLE)
                when (key as :string) == "VEHICLE_COUNT" 
                otherwise value)
    })
}

Expected output:

[
  {
    "commId": "1",
    "GENERAL": [
      {
        "ID": "G1",
        "VEHICLE_COUNT": "2",
        "PROPERTY_COUNT": "1"
      }
    ],
    "VEHICLE": [
      {
        "ID": "V1-1"
      },
      {
        "ID": "V1-2"
      }
    ],
    "PROPERTY": [
      {
        "ID": "P1-1"
      }
    ]
  },
  {
    "commId": "2",
    "GENERAL": [
      {
        "ID": "G2",
        "VEHICLE_COUNT": "1",
        "PROPERTY_COUNT": "2"
      }
    ],
    "VEHICLE": [
      {
        "ID": "V2-1"
      }
    ],
    "PROPERTY": [
      {
        "ID": "P2-1"
      },
      {
        "ID": "P2-2"
      }
    ]
  },
  {
    "commId": "3",
    "GENERAL": [
      {
        "ID": "G3",
        "VEHICLE_COUNT": "3",
        "PROPERTY_COUNT": "0"
      }
    ],
    "VEHICLE": [
      {
        "ID": "V3-1"
      },
      {
        "ID": "V3-2"
      },
      {
        "ID": "V3-3"
      }
    ]
  }
]

Getting totally wrong output so far:

[
  {
    "ID": "G1",
    "VEHICLE_COUNT": false,
    "PROPERTY_COUNT": "TODO"
  },
  {
    "ID": "G2",
    "VEHICLE_COUNT": false,
    "PROPERTY_COUNT": "TODO"
  },
  {
    "ID": "G3",
    "VEHICLE_COUNT": false,
    "PROPERTY_COUNT": "TODO"
  }
]
kimmy
  • 27
  • 5

1 Answers1

0

Edited: Update for dynamic transform

The below dataweave transform is not particularly attractive, but it might work for you.

Thanks to Christian Chibana for helping me find a dynmaic answer by answering this question: Why does Mule DataWeave array map strip top level objects?

%dw 1.0
%output application/json
---
payload map ((item) -> 
    (item - "GENERAL") ++
    GENERAL: item.GENERAL map (
        $ - "VEHICLE_COUNT"
          - "PROPERTY_COUNT"
          ++ { VEHICLE_COUNT: sizeOf (item.VEHICLE default []) }
          ++ { PROPERTY_COUNT: sizeOf (item.PROPERTY default []) }
    )
)

It is dynamic, so everything should be copied across as it comes in, with only the two fields you want being updated.

The output for this transform with the input you supplied is below. Only difference from your desired is that the counts are shown as numbers rather than strings. If you really need them as strings you can cast them like (sizeOf (comm.VEHICLE default [])) as :string,

[
  {
    "commId": "1",
    "VEHICLE": [
      {
        "ID": "V1-1"
      },
      {
        "ID": "V1-2"
      }
    ],
    "PROPERTY": [
      {
        "ID": "P1-1"
      }
    ],
    "GENERAL": [
      {
        "ID": "G1",
        "VEHICLE_COUNT": 2,
        "PROPERTY_COUNT": 1
      }
    ]
  },
  {
    "commId": "2",
    "VEHICLE": [
      {
        "ID": "V2-1"
      }
    ],
    "PROPERTY": [
      {
        "ID": "P2-1"
      },
      {
        "ID": "P2-2"
      }
    ],
    "GENERAL": [
      {
        "ID": "G2",
        "VEHICLE_COUNT": 1,
        "PROPERTY_COUNT": 2
      }
    ]
  },
  {
    "commId": "3",
    "VEHICLE": [
      {
        "ID": "V3-1"
      },
      {
        "ID": "V3-2"
      },
      {
        "ID": "V3-3"
      }
    ],
    "GENERAL": [
      {
        "ID": "G3",
        "VEHICLE_COUNT": 3,
        "PROPERTY_COUNT": 0
      }
    ]
  }
]
Johnson
  • 451
  • 2
  • 13
  • Thank you @Johnson. There is reasonable input control but will there be a convenient way of only updating the VEHICLE_COUNT and PROPERTY_COUNT instead of specifying other attributes? There are over 100 attributes that remains the same and only 2 attributes needs to be updated. – kimmy Jul 04 '19 at 06:21
  • Hi @kimmy - it should be doable and I have done something very similar in Dataweave 2.0, but I am struggling to get the syntax working for me with Dataweave 1.0. I think array mapping with the `-` operator is the most likely bet. I'll let you know if I get it working properly. – Johnson Jul 04 '19 at 22:01
  • Hi @kimmy - I have updated my answer with a dynamic dataweave transform – Johnson Jul 08 '19 at 03:37