65

Given a standard json string value:

$jsonString = '{ "baz": "quuz", "cow": [ "moo", "cud" ], "foo": "bar" }'

How can I get this to be all pretty with newlines, preferably without brute-force regex?

Simplest method I've found so far is:

$jsonString | ConvertFrom-Json | ConvertTo-Json 

However, that seems kinda silly.

Rynant
  • 23,153
  • 5
  • 57
  • 71
Eris
  • 7,378
  • 1
  • 30
  • 45
  • 10
    What is silly about the method you provided? Any other method will be either more complicated, or require an external module/library. – Rynant Jul 16 '14 at 20:01
  • 3
    It seems silly because it's taking a json string, doing all the work to convert it to an object, then converting it right back. I was hoping there was something obvious I missed like `Format-Xml` – Eris Jul 16 '14 at 20:03
  • 1
    `Format-XML` is a PSCX command, and I believe it does the same thing by converting a string to an XML object then converts back to a string. – Rynant Jul 16 '14 at 20:43
  • To minify any serialized entity, it has to be first be parsed (if only lexically). Only then does minification work, as the semantics are preserved. – AP. Oct 28 '16 at 18:48
  • Doesn't even work. ConvertFrom-Json in powershell 5.1 does not support -AsHashtable, so plan on crashing a lot. Use the Newtonsoft answer below – AUSTX_RJL Dec 11 '18 at 16:58
  • 3
    Json arrays will not round trip correctly through ConvertFrom-Json and ConvertTo-Json. This `[ { "hello": 1 } ]` becomes `{ "value": [ { "hello": 1 } ], "Count": 1 }`. @TechSpud's NewtonSoft approach is better – ben Feb 08 '19 at 13:59
  • What's silly? I find it very sleek actually. – woland Feb 17 '22 at 13:24

5 Answers5

31

Works for me. Parentheses make sure get-content is done before piping. Default depth of convertto-json is 2, which is often too low.

function pjson ($jsonfile) {
  (get-content $jsonfile) | convertfrom-json | convertto-json -depth 100 | 
    set-content $jsonfile
}
js2010
  • 23,033
  • 6
  • 64
  • 66
13

If you really don't want to go down the simplest route, which is to use inbuilt PowerShell functions | ConvertFrom-Json | ConvertTo-Json, here is another method, using JSON.net

# http://james.newtonking.com/projects/json-net.aspx
Add-Type -Path "DRIVE:\path\to\Newtonsoft.Json.dll"

$jsonString = '{ "baz": "quuz", "cow": [ "moo", "cud" ], "foo": "bar" }'
[Newtonsoft.Json.Linq.JObject]::Parse($jsonString).ToString()
TechSpud
  • 3,418
  • 1
  • 27
  • 35
  • 1
    Which is exactly the same technic only done with dotnet classes. ;-) – gbegerow Jul 21 '17 at 08:24
  • 2
    To support Arrays as well as Objects, use JToken, i.e. `[Newtonsoft.Json.Linq.JToken]::Parse($jsonString).ToString()` – ben Feb 08 '19 at 14:00
13

I put this in my profile

function PrettyPrintJson {
    param(
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        $json
    )
    $json | ConvertFrom-Json | ConvertTo-Json -Depth 100
}

Which works with pipes, and can be auto-completed, so it's at least somewhat less typing:

cat .\file.json | PrettyPrintJson
curl https://api.twitter.com/1.1/statuses/user_timeline.json | PrettyPrintJson
bobbaluba
  • 3,584
  • 2
  • 31
  • 45
  • 1
    This is my favorite solution. Easy and short. – gsscoder Nov 26 '20 at 16:17
  • I like it, it works for me, personally, but I would like to create a little script that I can check into source control for others to work. Appending the function to the top of the ps1 script isn't working, would you be a kind sole and put the two code blocks into one block that could be run from a ps1 script? – Sam Carleton Sep 22 '21 at 15:43
  • fits perfectly into `$profile`, thanks! – pavol.kutaj Oct 28 '21 at 09:28
6

Adding to @JS2010's answer I added logic to escape out certain characters and clean up my output even further. The parenthesis seems key and -depth is a big one since you can lose details without it, from what I've seen, on depth that goes beyond the default of 5, I believe it is.

function Format-Json ($JSON)
{
    $PrettifiedJSON = ($JSON) | convertfrom-json | convertto-json -depth 100 | ForEach-Object { [System.Text.RegularExpressions.Regex]::Unescape($_) }
    $PrettifiedJSON
}
Lee_Dailey
  • 7,292
  • 2
  • 22
  • 26
-4

I think what you are looking for is this:

$jsonString = @{ 
'baz' = 'quuz'
'cow'= "moo, cud"
'foo'= "bar" 
}
$jsonString|ConvertTo-Json

it produces this output

{
    "baz":  "quuz",
    "cow":  "moo, cud",
    "foo":  "bar"
}

Added note You could also array your cow values to "prettify" it a bit more:

 $jsonString = @{ 
    'baz' = 'quuz'
    'cow'= @("moo"; "cud")
    'foo'= "bar" 
    }

output:

{
    "baz":  "quuz",
    "cow":  [
                "moo",
                "cud"
            ],
    "foo":  "bar"
}
fampop
  • 58
  • 5
  • 2
    Your `$jsonString` is really a powershell object. This doesn't solve the problem. – Eris May 12 '17 at 18:30