How to compare JSON in powershell
Asked Answered
U

1

6

I have a requirement where I need to compare JSON object from a file to the JSON message which comes into Anypoint MQ queue. I am able to get the message from the queue. I have used below script but it is not working. I did both -eq and Compare-Object but they are not working.

$po_ps_output = $filemessagecontent | ConvertFrom-Json
$po_python_output = $mqmessagecontent.body | ConvertFrom-Json
$result = $po_ps_output -eq $po_python_output
Unanimity answered 1/10, 2019 at 12:40 Comment(0)
P
14

If you just want to know if the two JSON-originated objects differ, without needing to know how:

$contentEqual = ($po_ps_output | ConvertTo-Json -Compress) -eq 
                ($po_python_output | ConvertTo-Json -Compress)

Note:

  • ConvertTo-Json defaults to a serialization depth of 2 - use -Depth <n> if your data is more deeply nested to avoid truncation (potentiall data loss) - see this post.

  • Converting back to JSON may seem like an unnecessary step, but the -Compress standardizes the output formatting to a single line with no extra whitespace, which ensures that incidental variations in formatting in the input (if you had used the input JSON text directly) are ignored.


If you want to know how the two JSON-originated objects differ:

Note: The following is only useful in the following, limited scenario - a generic, robust solution would require much more effort:

  • The inputs have the same structure and differ only in property names / values.

  • The ordering of (equivalent) properties is the same.

Compare-Object (($po_ps_output | ConvertTo-Json) -split '\r?\n') `
               (($po_python_output | ConvertTo-Json) -split '\r?\n')

The output will show the lines that differ, each representing a single property or primitive value; e.g.:

InputObject                   SideIndicator
-----------                   -------------
      "DOB":  "12-03-1994"    =>
      "DOB":  "12-03-1999"    <=

Note:

  • => / <= indicate that the line is unique to the RHS / LHS.

  • Again, the explicit reconversion to JSON is done to ensure uniform formatting; in this case, a line-oriented pretty-printed format that enables property-by-property comparison.

  • Again, you may have to use -Depth to prevent truncation of data.

  • For interactive inspection of differences, you can try a difference-visualization tool, such as the one built into Visual Studio Code, by passing the two JSON strings in pretty-printed form via files to
    code --diff <file1> <file2>.


As for what you tried:

ConvertFrom-Json creates [pscustomobject] instances, so you're comparing two instances of that type:

  • If you use -eq, reference equality is tested for, because [pscustomobject] is a reference type and doesn't implement custom equality comparison.

    • Therefore, $po_ps_output -eq $po_python_output will only be $true if the two variables point to the very same object in memory - which is clearly not the case here, so you'll always get $false.
  • If you use Compare-Object, the two instances are compared by their .ToString() values.

    • As of PowerShell Core 7.0.0-preview.4, regrettably, calling .ToString() on an instance of [pscustomobject] yields the empty string (''), which should be considered a bug - see this GitHub issue.

    • Therefore, Compare-Object $po_ps_output $po_python_output (unhelpfully) considers the two instances equal and returns nothing, since equal objects are by default not output (use -IncludeEqual to include them).

Postmillennialism answered 1/10, 2019 at 16:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.