cancel
Showing results for 
Search instead for 
Did you mean: 

Mapping optional arrays of objects to arrays of objects

rpatrick00
Contributor

I have an input schema that contains some optional arrays of objects in one format that I need to map to a target schema with an array of objects in another format.

The problem I am having is how to get the Mapper to map the array if it is present and ignore it if it is not. For example, my mapping table expression for one field below works fine for documents where the Address element is present but causes an error if it is missing.

jsonPath($, "$MatchUpdatePartyPayload.Address[*].NonStandardUS.Line1") 

Thanks,
Robert

12 REPLIES 12

And if there are none then you’d want an empty array ?

The reason I ask is I am assuming these are all separate documents coming in to the mapper that have a field $MatchUpdatePartyPayload, which may or may not contain an array at the Address key.

For instances in which a document does not contain the specified array, what would you expect the expression to evaluate to in that instance?

It is not possible to simply skip the evaluation/mapping of that expression based on that key not being present. Some value needs to be used for the output of the expression and map to the target field. If you can group your documents, you could filter them based on the presence of this array and extract all values where applicable. Hope this helps in some way.

The actual payload is a little more complex than that.

The payload really looks like this (even this is somewhat simplified):

{
    "AddAttorneyStandingPayload": {
        "AttorneyID": <integer>,
        "CurrentStanding": <string>,
        "Date": <string>
    },
    "MatchUpdatePartyPayload": {
        "PartyID": <integer>,
        "Name": {
            "Title": <string>,
            "First": <string>,
            "Middle": <string>,
            "Last": <string>,
            "Suffix": <string>
        },
        "Address": [
            {
                "NonStandardUS": {
                    "Line1": <string>,
                    "Line2": <string>,
                    "Line3": <string>,
                    "City": <string>,
                    "State": <string>,
                    "Zip": <string>
                },
                "Foreign": {
                    "Line1": <string>,
                    "Line2": <string>,
                    "Line3": <string>,
                    "Line4": <string>
                }
            }
        ],
        "Phones": {
            "Phone": [
                {
                    "Number": <string>,
                    "Extension": <string>,
                    "Type": <string>
                }
            ]
        },
        "Emails": {
            "Email": [
                {
                    "EmailAddress": <string>,
                    "IsCurrent": <boolean>
                }
            ]
        }
    }
}

In this payload, the MatchPartyUpdatePayload element itself is optional (if the name, address, phone, and emails hasn’t changed, no need to specify the payload). Within the MatchPartyUpdatePayload element, Name, Address, Phones, and Emails are all optional (they are only needed if the data is being changed). Within some of those arrays, the objects themselves have optional fields (e.g., Line2 and Line3 for the NonStandardUS object).

The problem with the null-safe access is that it is putting the null at the lowest level. For example, let say that I have no Address element, what I am ending up with is a fully populated Address element with all values set to null. This doesn’t work for me because the NonStandardUS address element, if present, has 4 required fields and 2 optional fields. And the Foreign and NonStandardUS fields are mutually exclusive. My validation code verifies that any Address element has at least the 4 fields set to non-null/non-empty values. What would be better for me would be for the entire address list to be either empty or set to null without creating the nested address object and setting all 6 fields to null.

My company has some very large payloads (100s of fields with optional elements at various points in the message hierarchies, some of which are objects or arrays of objects). Having the Mapper set dozens of leaf node fields to null quickly becomes intractable since I would have to write a script to walk the entire tree and prune off the elements where all fields are set to null, starting at the leaf nodes and working my way back up. If I have to do that, I might as well just write a script to do the mapping the way I need it in the first place, right?

Hope this helps,
Robert

Unfortunately, you’re correct. Currently, every mapping defined by a Mapper will result in a value of some kind for the mapped field. There’s no way to conditionally omit a mapping. I noticed this deficiency a few weeks ago and raised it internally but we don’t have a solution yet. I’m going to link to your post in that discussion to underscore the need for this.

For now, I would agree that a Script would probably be the most straightforward means to your end.

I can see several possible solutions, depending on how fancy you want to get. The simplest solution would be similar to Null Safe Access option except that it would skip writing the null to the target field (and skip creating any intermediate object structure). Not sure what the mapper snap’s code looks like to know how hard this is but this seems like a reasonably simple solution.