Skip to content

how to "join" objects based on a common key #333

@darrencruse

Description

@darrencruse

Apologies I'm new to JSONata hopefully a dumb question and I just saw there is a slightly similar but not identical question to mine here:
#275

Our use case is we will have JSON with arrays from different REST apis whose entries we will need to match based on a common key and then transform them together into a single array of combined objects (although not just merge them actually pick certain properties or otherwise transform the property values so slightly different than #275 above which only merged the objects).

(also our goal in using JSONata is to have something a little friendly for non/semi-technical users and I'm hoping maybe there's a simpler solution than #275 which involves using a function we were hoping our use of JSONata would avoid that)

The test example I created in the JSONata Exercisor is as follows:

{
	"Employee": [{
			"SSN": "496913021",
			"FirstName": "Fred",
			"Surname": "Smith"
		},
		{
			"SSN": "496737199",
			"FirstName": "Darren",
			"Surname": "Cruse"
		}
	],
	"Contact": [{
			"ssn": "496913021",
			"Phone": [{
					"type": "home",
					"number": "0203 544 1234"
				},
				{
					"type": "office",
					"number": "01962 001234"
				},
				{
					"type": "mobile",
					"number": "077 7700 1234"
				}
			]
		},
		{
			"ssn": "496737199",
			"Phone": [{
					"type": "home",
					"number": "3146458343"
				},
				{
					"type": "mobile",
					"number": "315 782 9279"
				}
			]
		}
	]
}

So I was trying to match the array elements by the social security number ("SSN" in Employee and "ssn" in Contact).

This I thought I was getting close with but could never get it to work right:

$.Employee.{
    "SSN": $.SSN,
    "name": FirstName & " " & Surname,
    "phone": $$.Contact[ssn=$.SSN].Phone[type="mobile"].number	
}

But I can't seem to get the Contact to match by the Employee SSN I get:

[
  {
    "SSN": "496913021",
    "name": "Fred Smith"
  },
  {
    "SSN": "496737199",
    "name": "Darren Cruse"
  }
]

UPDATE: Just played a little more looking at the #275 solution and I did get this to work:

Employee.{
    "SSN": SSN,
    "name": FirstName & " " & Surname,
    "phone": ($$.Contact ~> $filter(function($contact){$contact.ssn = SSN})).Phone[type="mobile"].number	
}

Still wondering is this the simplest it can be?

If so then I'm wondering could I abstract it away somehow? e.g. Could I hide that filter behind a custom function I would provide something like:

Employee.{
    "SSN": SSN,
    "name": FirstName & " " & Surname,
    "phone": $matchKey($$.Contact, "ssn", SSN).Phone[type="mobile"].number	
}

should that be possible?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions