22

I would like to monkeypatch a PowerShell 2.0 environment where the upgrade to 3.0 is not possible at this time.

I am looking for a PowerShell 2.0 script implementation of the ConvertFrom-Json cmdlet and ConvertTo-Json cmdlet that are in PowerShell 3.0.

I am most interested in the ConvertFrom-Json, but ConvertTo-Json would also be nice.

Josh Petitt
  • 9,371
  • 12
  • 56
  • 104
  • 2
    to whomever voted to close for being off-topic, I understand you not. – x0n Jan 21 '15 at 22:51
  • 2
    He/She probably read this as a "script order", which I partly agree with. To use ITIL terminology: this is a request for service (wants a script), not an incident (script sample with errors). :) – Frode F. Jan 21 '15 at 23:03
  • 1
    @FrodeF., to add some information about my request, this is definitely a 'script order' since I don't want to write a version that is JSON compliant. I was hoping that there was an assembly that could be imported and leveraged. I was hoping there was a known solution to the monkeypatching problem, rather than me writing and debugging my own brand new script. If this is still off-topic I can move it somewhere else... – Josh Petitt Jan 21 '15 at 23:22
  • "Script orders" are usually frowned upon here. StackOverflow is for questions and answer for specific problems about programming, and "script orders" are usually closed for being "too broad". – Frode F. Jan 21 '15 at 23:54
  • You could take a look at [powershelljson.codeplex.com](https://powershelljson.codeplex.com/) Never tried it though. If that doesn't work, then you would probably need to write one yourself. You could write a wrapper that uses Json.Net or Web.Extensions ([sample](https://stackoverflow.com/questions/17601528/read-json-object-in-powershell-2-0)) to do some of the work. – Frode F. Jan 21 '15 at 23:58

3 Answers3

46
function ConvertTo-Json20([object] $item){
    add-type -assembly system.web.extensions
    $ps_js=new-object system.web.script.serialization.javascriptSerializer
    return $ps_js.Serialize($item)
}

function ConvertFrom-Json20([object] $item){ 
    add-type -assembly system.web.extensions
    $ps_js=new-object system.web.script.serialization.javascriptSerializer

    #The comma operator is the array construction operator in PowerShell
    return ,$ps_js.DeserializeObject($item)
}

If you're getting the error:

Add-Type : Could not load file or assembly 'System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35 or one of its dependencies. The system cannot find the file specified. "

... these registry commands can be run (more details):

   reg add hklm\software\microsoft\.netframework /v OnlyUseLatestCLR /t REG_DWORD /d 1 /f
   reg add hklm\software\wow6432node\microsoft\.netframework /v OnlyUseLatestCLR /t REG_DWORD /d 1 /f
StockB
  • 755
  • 1
  • 13
  • 33
Edward
  • 1,239
  • 13
  • 20
  • 6
    Here's a ConvertFrom function, based on the above. `function ConvertFrom-Json20([object] $item){ add-type -assembly system.web.extensions $ps_js=new-object system.web.script.serialization.javascriptSerializer return $ps_js.DeserializeObject($item) }`. Poorly formatted, sorry. – Geoff Aug 04 '15 at 15:52
  • 1
    Thanks Geoff! I added to the answer – Josh Petitt Aug 04 '15 at 17:39
  • 1
    If you do not have .NET 3.5 installed, you will get an error: "Add-Type : Could not load file or assembly 'System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35 or one of its dependencies. The system cannot find the file specified. " ... – Ivan Ignatiev Mar 04 '16 at 16:34
  • 2
    I get the error `Exception calling "Serialize" with "1" argument(s): "A circular reference was detected while serializing an object of type 'System.Management.Automation.PSMethod'` – Kellen Stuart Jul 18 '17 at 23:28
  • 2
    More info - `ConvertTo-Json20` can't handle a powershell object, as in `$obj = New-Object PsObject`. You will get the error above. Arrays have worked so far `$arr = @('va1','val2')` – Kellen Stuart Jul 19 '17 at 15:26
  • If you need to serialize a `PSCustomObject`, I would suggest converting it to a `HashTable` first. https://stackoverflow.com/questions/3740128/pscustomobject-to-hashtable – killjoy May 31 '19 at 13:34
  • When using the `ConvertTo-JSON20` above, I was receiving the error below when trying to update a list of sites from a JSON file to an updated list. "Exception calling "Serialize" with "1" argument(s): "A circular reference was detected while serializing an object of type `'System.Management.Automation.PSMethod'"` When I cast the array by using `$array = @()` it creates the array as a generic `Object[]`, however, if you explicitly cast the array as a string (by using `[string[]]$array = @()`, then `ConvertTo-JSON20` is able to convert the string to JSON. – Sean Bulger May 28 '19 at 18:27
2

Code with javascriptSerializer return objects with Dictionary inside. Modern convertfrom-JSON (4.0+) return objects only. This code transform deserialize object to modern output :)

function Iterate-Tree($jsonTree) {
    $result = @()
    foreach ($node in $jsonTree) {
        $nodeObj = New-Object psobject
        foreach ($property in $node.Keys) {
            if ($node[$property] -is [System.Collections.Generic.Dictionary[String, Object]] -or $node[$property] -is [Object[]]) {
                $inner = @()
                $inner += Iterate-Tree $node[$property]
                $nodeObj  | Add-Member -MemberType NoteProperty -Name $property -Value $inner
            } else {
                $nodeObj  | Add-Member -MemberType NoteProperty -Name $property -Value $node[$property]
                #$nodeHash.Add($property, $node[$property])
            }
        }
        $result += $nodeObj
    }
    return $result
}

function ConvertFrom-Json20{ 
    [cmdletbinding()]
    Param (
        [parameter(ValueFromPipeline=$true)][object] $PS_Object
    )

    add-type -assembly system.web.extensions
    $PS_JavascriptSerializer=new-object system.web.script.serialization.javascriptSerializer
    $PS_DeserializeObject = ,$PS_JavascriptSerializer.DeserializeObject($PS_Object) 

    #Convert Dictionary to Objects
    $PS_DeserializeObject = Iterate-Tree $PS_DeserializeObject

    return $PS_DeserializeObject
}
0

A little bit improved option:

function Iterate-Tree($jsonTree) {
$result = @()
foreach ($node in $jsonTree) {
    $nodeObj= New-Object psobject
    foreach ($property in $node.Keys) {
        if(-not ($property)){
        continue }
        
        if ($node[$property] -is [System.Collections.Generic.Dictionary[String, Object]] -or $node[$property] -is [Object[]]) {
            $nodeObj | Add-Member -MemberType NoteProperty -Name $property -Value (Iterate-Tree $node[$property])
        } else {
            $nodeObj | Add-Member -MemberType NoteProperty -Name $property -Value $node[$property]
            #$nodeHash.Add($property, $node[$property])
        }
    }
    $result += $nodeObj
}
return [Object]$result

}

  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Nov 25 '21 at 21:05