11

I want to parse JSON in PowerShell but I can't use the new v3 functions that are available in PowerShell. My first thought was to load the JSON.Net assembly and use that to parse the JSON string but it doesn't work as I expect it to.

I have this JSON:

$json = "{""Name"": ""Apple"",  
           ""Price"": 3.99,  
            ""Sizes"": [    
                 ""Small"",    
                 ""Medium"",
                 ""Large""]}"

I load the JSON.NET assembly with this code:

[Reflection.Assembly]::LoadFile("$currentPath\Newtonsoft.Json.dll”)

And tries to parse it with

$result = [Newtonsoft.Json.JsonConvert]::DeserializeObject($json)

Now I expect that $result["Name"] is Apple but I get nothing there. Any ideas?

The code ´$result.ContainsKey("Name")returnsTruebut$result.GetValue("Name")returnsnull`.

4 Answers 4

15

Ok, so here is how I did it so it works down to at least PowerShell v2 on Windows 2008.

First, load the Json.NET assembly for the version you would like to use, I took the .NET 3.5 version:

[Reflection.Assembly]::LoadFile("Newtonsoft.Json.dll")

I had the JSON in a file since it was used in a deployment configuration I wrote, so I needed to read the file and then parse the json

$json = (Get-Content $FileName | Out-String) # read file
$config = [Newtonsoft.Json.Linq.JObject]::Parse($json) # parse string

Now to get values from the config you need to to use the Item method which seems defined by PowerShell on hashtables/dictionaries. So to get an item that is a simple string you would write:

Write-Host $config.Item("SomeStringKeyInJson").ToString()

If you had an array of things you would need to do something like

$config.Item("SomeKeyToAnArray") | ForEach-Object { Write-Host $_.Item("SomeKeyInArrayItem").ToString() }

To access nested items you write

$config.Item("SomeItem").Item("NestedItem")

That's how I solved parsing JSON with Json.NET in PowerShell.

Sign up to request clarification or add additional context in comments.

1 Comment

You can also get nested values using the array syntax. $config["SomeItem"]["NestedItem"].ToString()
9

If you get here and are using Powershell 5.0, it's available in the powershell gallery

Install-Module Newtonsoft.Json
Import-Module Newtonsoft.Json

$json = '{"test":1}'
[Newtonsoft.Json.Linq.JObject]::Parse($json)

1 Comment

Be careful with this - it's not an official release and the Json.net version it contains dates back to October 2018
5

maybe this is what you're after :

http://poshcode.org/2930

    function Convert-JsonToXml {
PARAM([Parameter(ValueFromPipeline=$true)][string[]]$json)
BEGIN { 
   $mStream = New-Object System.IO.MemoryStream 
}
PROCESS {
   $json | Write-Stream -Stream $mStream
}
END {
   $mStream.Position = 0
   try
   {
      $jsonReader = [System.Runtime.Serialization.Json.JsonReaderWriterFactory]::CreateJsonReader($mStream,[System.Xml.XmlDictionaryReaderQuotas]::Max)
      $xml = New-Object Xml.XmlDocument
      $xml.Load($jsonReader)
      $xml
   }
   finally
   {
      $jsonReader.Close()
      $mStream.Dispose()
   }
}
}

function Write-Stream {
PARAM(
   [Parameter(Position=0)]$stream,
   [Parameter(ValueFromPipeline=$true)]$string
)
PROCESS {
  $bytes = $utf8.GetBytes($string)
  $stream.Write( $bytes, 0, $bytes.Length )
}  
}



$json = '{
    "Name": "Apple",
    "Expiry": 1230422400000,
    "Price": 3.99,
    "Sizes": [
        "Small",
        "Medium",
        "Large"
    ]
}'

Add-Type -AssemblyName System.ServiceModel.Web, System.Runtime.Serialization
$utf8 = [System.Text.Encoding]::UTF8                 
(convert-jsonToXml $json).innerXML

Output :

<root type="object"><Name type="string">Apple</Name><Expiry type="number">1230422
400000</Expiry><Price type="number">3.99</Price><Sizes type="array"><item type="s
tring">Small</item><item type="string">Medium</item><item type="string">Large</it
em></Sizes></root>

If you want the name node :

$j=(convert-jsonToXml $json)
$j.SelectNodes("/root/Name")

or

$j |Select-Xml -XPath "/root/Name" |select -ExpandProperty node

5 Comments

what is too complex ?? i've edited my answer and provide an example. BTW I dont think $json is a valid json ( check jsonlint.com )
You were correct about the json not being correct, I've updated it and removed the date part which made it correct. However, I do like your answer so you got a vote for that, but it doesn't answer my question for two reasons. 1. I've asked about how to do it with Json.NET. 2. I didn't want to parse json to xml, I wanted it parsed. I have found a solution with Json.Net that I'm trying that is really simple and will post that as answer soon.
See my answer for how I did it.
I will, but I have to wait 20 hours first.
not trying to troll anyone, just trying to explain why I do think it is too complex as well. Deserializing from string to xml and then to json, opens many possible errors for complex objects or with complex values (because we are "translating" across languages, pretty much when you would translate from English to Spanish and then to French. You WILL lose context and content).
1

None of the answers here so far made it straightforward to deserialize, edit, and serialize without Token PropertyName in state ArrayStart would result in an invalid JSON object errors. This is what ended up working for me.

Assuming $json contains a valid json string this deserializes to a hashtable:

$config = [Newtonsoft.Json.JsonConvert]::DeserializeAnonymousType($json, @{})

Or, if you need to maintain key order:

$config = [Newtonsoft.Json.JsonConvert]::DeserializeAnonymousType($json, [ordered]@{})

Then you can work with the data as a normal hashtable, and serialize it again.

$sb = [System.Text.StringBuilder]::new()
$sw = [System.IO.StringWriter]::new($sb)
$jw = [Newtonsoft.Json.JsonTextWriter]::new($sw)
$jw.Formatting = [Newtonsoft.Json.Formatting]::Indented
$s = [Newtonsoft.Json.JsonSerializer]::new()

$s.Serialize($jw, $config)
$json = $sb.ToString()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.