PowerShell 2.0 ConvertFrom-Json and ConvertTo-Json implementation
Asked Answered
L

3

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.

Laellaertes answered 21/1, 2015 at 22:15 Comment(5)
to whomever voted to close for being off-topic, I understand you not.Intussusception
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). :)Iain
@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...Laellaertes
"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".Iain
You could take a look at 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) to do some of the work.Iain
R
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
Radom answered 17/4, 2015 at 3:21 Comment(7)
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.Tapster
Thanks Geoff! I added to the answerLaellaertes
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. " ...Bullen
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'Liebman
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')Liebman
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.Servomotor
If you need to serialize a PSCustomObject, I would suggest converting it to a HashTable first. https://mcmap.net/q/392447/-pscustomobject-to-hashtableIntelligible
C
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
}
Contain answered 28/9, 2018 at 11:23 Comment(0)
P
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

}

Perished answered 25/11, 2021 at 17:1 Comment(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.Owades

© 2022 - 2024 — McMap. All rights reserved.