I am using Powershell to edit a json-file. The indentation in the edited file looks weird and the lines are not in the order I want them to be.
I have used this code to edit my json-file:
$appSettings = Get-Content C:testappsettings.json | ConvertFrom-Json
$httpData = @{"Url"="http://*:2201"}
$httpsData = @{}
$httpsData.Add("Url","https://*:2203")
$httpsData.Add("SslProtocols",$("Tls12", "Tls13"))
$httpsData.Add("Certificate",@{"Subject"="SubjectName";"Store"="My";"Location"="CurrentUser";"AllowInvalid"="True";})
$endPointsData = @{}
$endPointsData.Add("Http",$httpData)
$endPointsData.Add("HttpsInlineCertStore",$httpsData)
$KestrelData = @{}
$KestrelData.Add("EndPoints",$endPointsData)
$appSettings | Add-Member -Name 'Kestrel' -Value $KestrelData -MemberType NoteProperty
$appSettings | ConvertTo-Json -Depth 6 | Out-File "C:testappsettings.json"
This is the result I want:
This is the result I get:
How to fix this?
Thanks.
2
Answers
This should do the trick.
($appSettings | ConvertTo-Json -Depth 6).Replace(' ',' ') | Out-File "C:testappsettings.json"
Problems:
The ordering issue is due to the fact that you are using hashtables (
@{ ... }
), whose entries are inherently unordered.[ordered] @{ ... }
), which preserve definition order.The pretty-printing behavior of
ConvertTo-Json
in Windows PowerShell is unfortunate: 4 spaces per indentation level and 2 spaces between a property name and the (start of) its value, with nested content indented relative to the position of the opening delimiter ({
or[
), with the closing delimiter at the same indentation level as the opening one.Additionally, even empty arrays and objects have multiline representations.
All in all, this makes for a needlessly wide and/or tall representations that make deep hierarchies hard to grasp.
Pretty-printing in PowerShell (Core) 7+ is now more sensible and works the way you want: 2 spaces per indentation level, 1 space between property name and the (start of) its value, with nested content indented relative to the start of the enclosing property and the closing delimiter at the same indentation level as the property itself.
Empty arrays and objects now have inline representations (e.g.
"Foo": []
)Note the neither PowerShell edition offers ways to customize pretty-printing (only a way to disable it, with `-Compress).
Solutions:
Use the
ConvertTo-AdvancedJson
cmdlet from the third-partyPSAdvancedJsonCmdlet
module (install withInstall-Module -Scope CurrentUser PSAdvancedJsonCmdlet
, for instance): it is essentially a backport of the betterConvertTo-Json
implementation found in PowerShell (Core) 7+If installing modules isn’t an option, and short of writing your own JSON serializer, you can use a quick-and-dirty, suboptimal approximation of the desired pretty-printing, using a single, regex-based string substitution via the
-replace
operator, as shown in the sample code below.Short of writing your own JSON serializer, there is a string-substitution solution with stateful, line-by-line processing, wrapped in a
Format-Json
custom function in this answer – you can use it instead ofConvertTo-Json
, because it has the latter built in.-Indentation
parameter.The following is a self-contained example that:
Uses
[ordered] @{ ... }
hashtables to ensure the desired ordering, via a single, nested ordered-hashtable literal.Is cross-edition-compatible:
ConvertTo-AdvancedJson
if available, and falls back to the quick-and-dirty, suboptimal string-replacement technique.Output with the quick-and-dirty workaround:
Output in PowerShell 7+ or with
ConvertTo-AdvancedJson
: