4

Is there some simple way to extend one JSON file with another and save the output to yet another file using PowerShell? Currently I'm attempting to write a recurrent function that will allow me to do that*, but maybe there is a simpler solution out there?

*iterate over properties of a JSON converted to a PSCustomObject and replace them if needed (actually check my answer below)

Edit: I need to do something similar to what jquery.extend does so, my input is:

{
    "name": "Some name",
    "value": 1,
    "config": {
        "debug": false,
        "output": "c:\\"
    }
}

And

{
    "value": 2,
    "config": {
        "debug": true
    },
    "debug": {
        "log": true
    }
}

And my output is supposed to be:

{
    "name": "Some name",
    "value": 2,
    "config": {
        "debug": true,
        "output": "c:\\"
    },
    "debug": {
        "log": true
    }
}

P.S. Generally I need to write a script that can be run from a batch file and does not require 3rd party libraries (is limited to Windows resources). I tried my luck with Cscript JavaScript, but I decided against using it when I found out, that the only built in method to parse JSON is to eval it.

Community
  • 1
  • 1
jahu
  • 5,427
  • 3
  • 37
  • 64

2 Answers2

10

After a lot of trial and error I managed to write my recurrent function.

function ExtendJSON($base, $ext)
{
    $propNames = $($ext | Get-Member -MemberType *Property).Name
    foreach ($propName in $propNames) {
        if ($base.PSObject.Properties.Match($propName).Count) {
            if ($base.$propName.GetType().Name -eq "PSCustomObject")
            {
                $base.$propName = ExtendJSON $base.$propName $ext.$propName
            }
            else
            {
                $base.$propName = $ext.$propName
            }
        }
        else
        {
            $base | Add-Member -MemberType NoteProperty -Name $propName -Value $ext.$propName
        }
    }
    return $base
}
$file1 = (Get-Content $args[0]) -join "`n" | ConvertFrom-Json
$file2 = (Get-Content $args[1]) -join "`n" | ConvertFrom-Json
#Out-File produces incorrect encoding
#ExtendJSON $file1 $file2 | ConvertTo-Json | Out-File $args[2]

$output = ExtendJSON $file1 $file2 | ConvertTo-Json
#Save output as BOMless UTF8
[System.IO.File]::WriteAllLines($args[2], $output)

I have no idea if this is the easiest way to achieve my goal, but it does get the job done. This also doubles as answer to the how to combine\combine\merge two PSCustomObjects, which appears no one has asked yet (maybe I'm breaching open doors here). I'm nearly inclined to rewrite the question as such, but my gut is telling me there might be different methods of extending JSON using PowerShell, which don't necessarily require converting my JSON files to PSCustomObject.

jahu
  • 5,427
  • 3
  • 37
  • 64
  • 1
    Wow, you beat me to it :). Actually there is some existing PS implementations of object joining: [Join-Object](http://blogs.msdn.com/b/powershell/archive/2012/07/13/join-object.aspx), [Join-Object 3.0](http://poshcode.org/1818) and some others, less sophisticated. Recursive one is nice, but keep in mind, that [PowerShell has recursion limits](http://stackoverflow.com/questions/10755699/how-can-i-configure-call-depth-in-powershell). – beatcracker Mar 29 '15 at 20:15
  • @beatcracker The 100 level limit shouldn't be a problem as I'm dealing with rather simple JSON files (namely the package.json configuration files for nw,js applications). – jahu Mar 29 '15 at 20:41
-1

If you're running PowerShell 3.0 or higher, you can use built-in ConvertFrom-Json\ConvertTo-Json cmdlets.

If you're stuck with PS 2.0, have a look at Convert between PowerShell and JSON project or this module.

beatcracker
  • 6,714
  • 1
  • 18
  • 41
  • I'm already using those ConvertFrom-Json cmdlets. So technically your answer doesn't answer the question, but it gave me a new idea, which might be just what I'm looking for. I assumed that JSON objects are a different type in PowerShell, while in fact it appears I just convert them to regular objects. In other words if PowerShell has a function to extend\combine two objects, it would be exactly what I'm looking for. Gotta check... – jahu Mar 29 '15 at 15:06
  • @jahu You don't need "function" for that, the output from `ConvertFrom-Json` is native `PsObject`, so you can just add objects together and export result to file: `$FromJson1 + $FromJson2 | ConvertTo-Json | Out-File 'c:\new.json'` – beatcracker Mar 29 '15 at 15:44
  • @jahu Also, if you provide example JSON files and expected result, I could help you further. – beatcracker Mar 29 '15 at 15:48
  • Finally managed to write my function (check my answer). If I were to reword my question it would be: is there a simpler way to merge JSONs than what I have in my answer. – jahu Mar 29 '15 at 20:05
  • @jahu Nice one, and sorry for this junk code in my comment that was trying to add objects (`$FromJson1 + $FromJson2`), surely it doesn't work and I don't know what I was thinking at that time... – beatcracker Mar 29 '15 at 20:17