skip to Main Content

I have a file with content

{
  "Names" : {"first" : "Chuck", "second" : "Norris"},
  "Numbers" : {"one" : "1", "two" : "2"}
}

I can read/write and convert it with ConvertFrom-Json and ConvertTo-Json, this is no problem. And I can change f.e. "Chuck" into "Carlos Ray".
But how can I

  • add a new tuple like f.e. Months ("1st" : "January" …)
  • add a row inside an existing tuple, f.e. "Numbers" -> "three" : 3
  • delete a row
  • delete a tuple

? That means: I want to read the file and convert it into $variable, modify the $variable and convert and write the file.

Thank you very much

2

Answers


  1. $json = @'
    {
      "Names" : {"first" : "Chuck", "second" : "Norris"},
      "Numbers" : {"one" : "1", "two" : "2"}
    }
    '@ | ConvertFrom-Json
    

    Add a new tuple like f.e. Months ("1st" : "January" …)

    $json.PSObject.Properties.Add(
        [psnoteproperty]::new(
            'Months',
            [pscustomobject]@{ '1st' = 'January' }))
    $json | ConvertTo-Json
    

    Add a row inside an existing tuple, f.e. "Numbers" -> "three" : 3

    $json.Numbers.PSObject.Properties.Add(
        [psnoteproperty]::new('three', '3'))
    $json | ConvertTo-Json
    

    Delete a row

    Removing the added Months property from 1st example.

    $json.PSObject.Properties.Remove('Months')
    $json | ConvertTo-Json
    

    Delete a tuple

    Removing the added three object.

    $json.Numbers.PSObject.Properties.Remove('three')
    $json | ConvertTo-Json
    
    Login or Signup to reply.
  2. To complement Santiago Squarzon’s helpful answer:

    ConvertFrom-Json is PowerShell’s cmdlet for parsing JSON text into object graphs.

    • In Windows PowerShell, you invariably get [pscustomobject] graphs, and Santiago’s answer shows you how to work with those.

    • In PowerShell (Core) 7+, you have the option to get (ordered) [hashtable] graphs, using the -AsHashTable switch.

    Hashtable-based object graphs are generally lighter-weight and better suited to later modification, such as in your case:

    # PS 7+ ONLY
    $fromJson = @'
    {
      "Names" : {"first" : "Chuck", "second" : "Norris"},
      "Numbers" : {"one" : "1", "two" : "2"}
    }
    '@ | ConvertFrom-Json -AsHashtable
    
    # --- UDPATE / ADDITION operations
    
    # Update a nested entry.
    $fromJson.Names.first = 'Carlos Ray'
    
    # Add a new top-level entry
    $fromJson.Months = [ordered] @{ '1st' = 'January'}
    
    # Add a new nested entry
    $fromJson.Numbers.three = 3
    
    # Print the state of the hahstable now.
    $fromJson | Out-Host
    
    # --- REMOVAL operations
    
    # Remove a top-level entry
    $fromJson.Remove('Names')
    
    # Remove a nested entry
    $fromJson.Numbers.Remove('two')
    
    $fromJson | Out-Host
    

    Output:

    # After entry updates / additions.
    Name                           Value
    ----                           -----
    Names                          {[first, Carlos Ray], [second, Norris]}
    Numbers                        {[one, 1], [two, 2], [three, 3]}
    Months                         {[1st, January]}
    
    
    # After entry removals.
    Name                           Value
    ----                           -----
    Numbers                        {[one, 1], [three, 3]}
    Months                         {[1st, January]}
    

    Note:

    • In PowerShell 7.3+, -AsHashtable returns a graph of [System.Management.Automation.OrderedHashtable] instances, which preserve the entry-definition order, just like PowerShell’s [ordered] @{ ... } hashtables[1]; in v7.2-, they were regular [System.Collections.Hashtable] instances.

    • Either way, however, in order to be JSON-compliant, the hashtables returned by ConvertFrom-Json are case-sensitive with respect to key lookups, unlike PowerShell’s regular hashtables (@{ ... }, [ordered] @{ ... }).

    • Choosing whether to use -AsHashTable or not:

      • While using hashtable object graphs is generally preferable (lighter-weight, easier to modify), there are situations where obtaining [pscustomobject] graphs is still a must, given that hashtables and objects aren’t fully interchangeable.

      • Conversely, if your JSON contains object with property names that are mere case variations of each other, -AsHashTable is a must, given that true property access in PowerShell is inherently case-insensitive; e.g.:

        # !! FAILS, because a [pscustomobject] instance cannot
        # !! have property names that differ in case only.
        '{ "foo": 1, "FOO": 2 }' | ConvertFrom-Json
        
        # OK - the hashtable returned is case-sensitive.
        '{ "foo": 1, "FOO": 2 }' | ConvertFrom-Json -AsHashTable
        

    [1] These literals become [System.Collections.Specialized.OrderedDictionary] instances, which, in fact, the OrderedHashtable implementation uses behind the scenes as well, albeot case-sensitively.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search