0

I found a powershell deep compare object (https://github.com/kjelderg/Compare-DeepObject) and derived a recursive Json Compare Function for powershell.

The function generally seems to work fine, but its too slow for my purpose. For a batch compare it needs 8 minutes.

How can I speed up the processs?

Thanks

Alex


# walk through the two objects and generate a diff
# This extends compare-object which itself only does shallow comparisons.

# To use, impor   t-module <thisFileName>
#  Compare-DeepObject $foo $istar

function Compare-Json2 {
    [CmdletBinding()]
    param (
    [Parameter(Mandatory=$true)][AllowNull()]$soll,
    [Parameter(Mandatory=$true)][AllowNull()]$ist,
    $isFile
# TODO: max-depth
    )
    PROCESS {
 
        $diff = [PSCustomObject]@{
            istJson = '{}'
            sollJson = '{}'
            difference = @()
        }


    if($isFile) {
        if ($ist -eq $soll) {
            $diff.difference += 'istFile == Soll File! Big Error in Testskript!'
            return $diff
        }
        if(Test-Path $ist) {
            $ist = Get-Content $ist
        }
        else {
            if(Test-Path $soll) {
            $diff.difference += 'istFileDoesNotExists'
            }
            return $diff
        }

        if(Test-Path $soll) {
            $soll = Get-Content $soll
        }
        else {
            $diff.difference += 'sollFileDoesNotExists'
            return $diff
        }
    }



    $diff.istJson = ($ist | ConvertFrom-Json) | ConvertTo-Json -Depth 100 -Compress
    $diff.sollJson = ($soll | ConvertFrom-Json) | ConvertTo-Json -Depth 100  -Compress
        $ist = $ist | ConvertFrom-Json -Depth 100
        $soll = $soll | ConvertFrom-Json -Depth 100
        $diff.difference = Compare-JsonObjectRecursive -soll $soll -ist $ist -node $null
#   }
    return $diff

    } # End PROCESS
} # End function$

function Compare-JsonObjectRecursive {
    [CmdletBinding()]
    param (
    [Parameter(Mandatory=$true)][AllowNull()]$soll,
    [Parameter(Mandatory=$true)][AllowNull()]$ist,
    $node
# TODO: max-depth
    )
    PROCESS {
 


# if one side is null, return the other side.
if($soll -eq $null -and $ist -ne $null) { return @{ soll=$null; ist=$ist} }
if($ist -eq $null -and $soll -ne $null) { return @{ ist=$null; soll=$soll} }
if($soll -eq $null -and $ist -eq $null) { return }

# compare data types

$differences = @{}
#$differences = New-Object PSCustomObject

if (($ist -is [PsCustomObject]) -and ($soll -is [array])) {
    [array]$ist = $ist
}
if (($ist -is [array]) -and ($soll -is [PsCustomObject])) {
    [array]$soll = $soll
}

if($soll -is [array]) { # Recurse for each element of an array
    for($i = 0; $i -lt [math]::max($soll.length, $ist.length); $i++) {
        if ($node) {$node = "$node[$i]"}
        else {$node = "[$i]"}
        
        Compare-JsonObjectRecursive -soll $soll[$i] -ist $ist[$i] -node $node 
    }
} 

elseif ($soll -is [PSCustomObject]) { # Recurse for each property of a PSCustomObject
    # walk both sets of keys^Wproperty names with this cool get-unique magic.
    $keys = (@($soll.PSObject.properties.name) + @($ist.PSObject.properties.name)) | Sort-Object | get-unique
    
    if ($node) {$node = "$node."}
    else {$node = ""}
    foreach($key in $keys) {
        Compare-JsonObjectRecursive -soll $soll.$key -ist $ist.$key -node "$node$key"
    }
}
else {
if($soll -ne $ist) {
    $differences[$node] = @{soll = $soll; ist = $ist}
    return $differences
    }
} 


    } # End PROCESS
} # End function$

Farbkreis
  • 604
  • 3
  • 12
  • Depends on what kind of diff you need. I would try: Read JSON as text, optionally parse and reformat such that each value stands on its own line, compare lines using `Compare-Object` or another text comparison function. – zett42 Mar 30 '21 at 09:01
  • 1
    "How can I speed up the process?" - depends a lot on the specific context of your code. For example, you could remove parts of the function you don't need, run your batch in parallel to do multiple comparisons at the same time, or rewrite parts of it in a compiled language (e.g. C#). – mclayton Mar 30 '21 at 12:18
  • 1
    Consider using `ConvertFrom-Json -AsHashTable` rather than heavy PSObjects. [Avoid using the increase assignment operator (`+=`)](https://stackoverflow.com/a/60708579/1701026) (even for building strings) as it is exponentially expensive, create a collection/list and use the `Add` method instead. – iRon Mar 30 '21 at 15:25

0 Answers0