Home > Software design >  How to add exact values to a psobject in Powershell?
How to add exact values to a psobject in Powershell?

Time:06-08

I'm doing a script in powershell where i'm modifying the Chrome Bookmarks file. This is what i want to do.

  1. Read the file and parse the Json (Done)
  2. Check if a certain folder is added, if it isn't, add it.
  3. Parse again the object to Json, and save a new bookmark file. (i know how to do it)

This is how i convert it to Object:

$BkmrkJson = Get-Content $GoogleBkmrk | ConvertFrom-Json

And this is how i'm adding a new Object to the current "Childrens(Urls or bookmarks)".

$BkmrkJson.roots.bookmark_bar.children  = New-Object -TypeName psobject -Property @{children=@();date_added="";date_modified="";guid="";id="";name="HV2";type="folder"}

My main problem, it's that when i add it, it isn't respecting the order of the properties. The usual order it's "children, date_added, date_modified, guid, id, name, type".

enter image description here

I add some values in blank, because Chrome adds new values automatically, after i add that value, or children, i parse again the psobject to Json.

$MyFinalJson = ConvertTo-Json $BkmrkJson -Depth 9

But when i create the file, it wasn't made correctly. So my principal question it's, how i can add correctly a new object to the parsed one, so when i parse it again, can recognize correctly the new ones.

CodePudding user response:

hashtables (@{ ... }) are inherently unordered in PowerShell / .NET, i.e the order in which their entries are later enumerated isn't guaranteed, which means that by the time your New-Object call receives its -Property argument, the definition order of the entries in the hashtable is already lost.

However, PowerShell v3 offers syntactic sugar for constructing custom objects ([pscustomobject] (aka [psobject])), in which case the order of entries, i.e. the order of the resulting properties is guaranteed to reflect the definition order, namely if you cast a hashtable to [pscustomobject]:

$BkmrkJson.roots.bookmark_bar.children  = 
  [pscustomobject] @{
    children=@();  # Note: ";" only strictly needed in *single-line* defs.
    date_added="";
    date_modified="";
    guid="";
    id="";
    name="Humach V2";
    type="folder"
  }

Note that in cases where you do want to stick with a hashtable (dictionary), you can "cast" a hashtable literal to [ordered], which also guarantees preserving the input order; specifically, this syntactic sugar creates an ordered hashtable, i.e. a System.Collections.Specialized.OrderedDictionary instance, which also implements the IDictionary interface, but (a) enumerates its entries in definition order and (b) allows accessing entries by positional index, as an alternative to using a key as the index; e.g.:

$orderedHashTable = [ordered] @{ zebra = 26; quebec = 17; alpha = 1}

$orderedHashTable.Keys # -> 'zebra', 'quebec', 'alpha'

# Access by key.
$orderedHashTable['quebec'] # -> 17

# Access by positional index
$orderedHashTable[0] # -> 26 (key 'zebra')
  • Related