Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Simulate an inner join between two JSON responses of an API call

I have Googled and seen this: In PowerShell, what's the best way to join two tables into one?

However, how can I do the JOIN without having that? Because our PS does not come with it and I don’t think we have permission to install new commands and we are on 5.1 too. So it has to be something built-in.

Now the question:
I have two APIs that I call with Invoke-RestMethod and they send me a array of JSON response like so:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

[
{ "FirstName" : "Hi",
"Code" : 123
},
{ "FirstName" : "Bye",
"Code" : 456
}
]

so let’s say we have $res1 and $res2 with some response like above in them and I want to do the JOIN on Code field.
How can I do this without using the Join-Object?

>Solution :

You can put your own simple Merge-Object command together like so:

function Merge-Object {
  param(
    [Parameter(Mandatory)]
    [array]$Left, 
    
    [Parameter(Mandatory)]
    [array]$Right, 
    
    [Parameter(Mandatory)]
    [string]$On)

  # create an index/correlation table from the right-hand collection
  # we'll use this to look up values based on the left-hand items' key property later
  $correlationTable = @{}
  $Right |ForEach-Object { 
    $key = $_.$On
    if ($null -ne $key) {
      $correlationTable[$key] = $_ 
    }
  }

  # iterate over the left-hand collection, try to correlate with right
  $Left |Where-Object {$null -ne ($key = $_.$On) -and $correlationTable.ContainsKey($key)} |ForEach-Object {
    # look up corresponding row in right-hand collection
    $correlated = $correlationTable[$_.$On]

    # extract property names from current object
    $existingNames = @($_.psobject.Properties.Name)

    # generate property selectors for non-overlapping property names on the right
    $selectors = $correlated.psobject.Properties.Name |Where-Object {$_ -notin $existingNames} |ForEach-Object {
      @{Name="$_"; Expression=[scriptblock]::Create("`$correlated.'$_'")}
    }

    # create new joined object
    $_ |Select-Object -Property @($existingNames;$selectors)
  }
}

Then use it like:

$res1 = @'
[
  {
    "FirstName": "Jane",
    "Code": 123
  },
  {
    "FirstName": "Robert",
    "Code": 456
  }
]
'@ |ConvertFrom-Json

$res2 = @'
[
  {
    "LastName": "Doe",
    "Code": 123
  },
  {
    "LastName": "Paulson",
    "Code": 456
  }
]
'@ |ConvertFrom-Json

Merge-Object -Left $res1 -Right $res2 -On Code |ConvertTo-Json

Which should give you:

[
  {
    "FirstName": "Jane",
    "Code": 123,
    "LastName": "Doe"
  },
  {
    "FirstName": "Robert",
    "Code": 456,
    "LastName": "Paulson"
  }
]
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading