Setting up my Windows PCs from scratch is a pain in the ass. I wanted to automate some of the mundane tasks and it turned out to be a PowerShell script called “Genesis” mainly for my personal use.
I used PowerShell because it’s quite flexible, straightforward and its VS Code support works just great. The problem is that there are only two configuration file formats PowerShell could recognize and they are terrible: JSON and XML.
JSON And XML Are Not Good For Humans
JSON is a terrible choice for storing human-edited configuration. People have already written about it. It doesn’t support comments, you have to constantly juggle the syntactic elements like the comma after the last element in a list, configuration keys always require quotes even when not needed. JSON can be a perfect serialization format between machines, like an API response, but never for manually edited configuration.
XML is better than JSON in some areas: it supports comments and a human can easily add or remove elements without touching any other part of the document. However, XML is extremely bloated! All the repetitive and redundant characters, closing tags. I think it’s friendlier than JSON as long as you are not the person editing it. XML has had problems with security for a long time. It’s far from being a pleasant medium for human-edited configuration files.
Both formats have been used as a configuration format for decades of course. They are built in most of the modern programming frameworks. They were my only choice when developing the tool on PowerShell.
Alternatives Aren’t Any Better
There are some nice, human-oriented alternative configuration formats like YAML and TOML. YAML is complicated and ambiguous. TOML is mostly great but not visually hierarchical (I mean, you can indent it artificially but it feels out of place). I prefer visual hierarchy for my own configurations. Although there are PowerShell modules handling those formats I didn’t want my script externally depend on those.
PSD1 is the filename extension for PowerShell module descriptions. PowerShell modules are like NPM libraries that you can install on demand. A module’s PSD1 file contains metadata for that module. It’s basically a PowerShell script that defines a PowerShell object (PSObject), similar to JSON in that sense.
Although PSD1 is specific for module descriptions, PowerShell provides an API to load any kind of data from any PSD1 file using
Here is a sample PSD1:
It pretty much looks like a tame JSON, doesn’t it?
What makes PSD1 great? First, it doesn’t have any of the problems JSON and XML have:
- It’s visually hierarchical yet it doesn’t require rigid syntactic elements like commas for multi-line items.
- It allows comments, both inline and block.
- It supports integer, float, boolean, string, array and map data types. It actually supports more than that, like bytes, characters, thanks to .NET, but those should be sufficient for a portable data format.
- Quote characters around field names are optional, unlike JSON.
- It doesn’t need
\characters to be quoted in strings, because quote character in PowerShell is
`. That especially makes Windows-style file paths significantly more readable.
- Data types can be strongly specified, e.g.
key = [string]3.
- It supports multiline strings and here-strings.
- The parser comes built-in with PowerShell. Conversely, I don’t think any other platform has a parser for these. You could get by using PowerShell parsers in C# but they wouldn’t be performant.
PSD1 is not fully a PowerShell script either. Using
Import-PowerShellDataFile cmdlet doesn’t run the code in the script, only gathers the data, so it’s not subject to security vulnerabilities, unlike YAML.
In overall, PSD1 feels mostly like what JSON should have been with some weird quirks from the world of PowerShell, like the
@ prefix in front of array and map declarations, the
$ prefix in front of boolean values and alternating use of
PSD1 was a welcome surprise to me. I actually enjoyed how easily it could be edited and how readable it is. Although it wasn’t designed for generic configuration use, it feels like a solid alternative to JSON for PowerShell-specific scenarios. I don’t see it growing to be a YAML competitor but it certainly emphasizes what humans need in such a format. Who knows, it might eventually shape the future of the configuration formats.