Search code examples
jsonpowershell-4.0

Parse json with empy string key in powershell


ConvertFrom-Json fails with message "Cannot process argument because value of "name" is not valid." "{ """": ""test""}" | ConvertFrom-Json

Is there better way than doing it manually?


Solution

  • While the JSON RFC does permit empty keys[1] , ConvertFrom-Json does not, unfortunately, for technical reasons: it returns objects of type [pscustomobject], which are not permitted to have a property whose name is the empty string.

    By contrast, PowerShell's [hashtable] ([System.Collections.Hashtable]) type and its ordered-keys sibling ([System.Collections.Specialized.OrderedDictionary]) do permit entries with empty-string key values (1 per instance).

    ConvertFrom-Json doesn't offer creating hashtables, but the third-party newtonsoft.json module does. The module is a wrapper around the widely used and Microsoft-recommended Json.NET library. It comes with alternative cmdlets ConvertFrom-JsonNewtonsoft and ConvertTo-JsonNewtonsoft:

    PS> '{ "": "test"}' | ConvertFrom-JsonNewtonsoft
    
    Name                           Value
    ----                           -----
                                   test
    

    Update, as of Oct 2020: The module was last updated in May 2019, and the bundled Newtonsoft.Json.dll assembly is quite old: it is version 8.0, whereas the current version as of this writing is 12.0. The module's source code can be found here.

    The output type is [System.Collections.Specialized.OrderedDictionary], i.e., a hashtable with ordered keys, and in this case is the equivalent of the following ordered hashtable literal:
    [ordered] @{ '' = 'test' }

    You can use either .'' or [''] to reference the entry with the empty key:

    PS> $o = $'{ "": "test"}' | ConvertFrom-JsonNewtonsoft
    PS> $o.'', $o['']
    test
    test
    

    Installation

    In PowerShell v5 without additional setup, and in v4 (and also v3) after having installed the PowerShell PackageManagement modules, you can install the module from the PowerShell Gallery as follows from an elevated console:

    Install-Module Newtonsoft.Json
    

    Alternatively, use Install-Module -Scope CurrentUser Newtonsoft.Json to install for the current user only.


    [1] A JSON name (key) is defined as a string (member = string name-separator value), and a "string is a sequence of zero or more Unicode characters" (emphasis added).