1

Using Splatting Hashtable for to set parameters and works well. I am passing to a function as New-ADUser @param, the values that are set in splatting will be created in Active Directoy . However, my script will be running somewhere else. The Json file will be manipulated by the user.

How I can pass to this New-ADUser @param function the Json file instead Splatting table.

Thanks for your help.

mklement0
  • 382,024
  • 64
  • 607
  • 775
Ashlyne B
  • 11
  • 3
  • 1
    Convert the json to an object with `ConvertFrom-Json` an take the properties to create a splatting Hashtable – Theo Jul 12 '21 at 18:26

2 Answers2

3

Note: The following assumes that your JSON config file:

  • contains an object whose property names match the parameter names of the target cmdlet, New-ADUser
  • and that the property values are limited to strings, numbers, Booleans, and nested objects that PowerShell can cast to the parameter's type, based on the constraints explained in this answer.

These constraints ensure that a hashtable representation of that object can be used as-is for parameter splatting.


If you're running PowerShell (Core) 7+, you can take advantage of ConvertFrom-Json's
-AsHashtable parameter.

# Load JSON from file 'config.json' into a [hashtable] instance.
$params = Get-Content -Raw config.json | ConvertFrom-Json -AsHashtable

# Use the hashtable for splatting.
New-ADUser @params

In Windows PowerShell (whose latest and final version is 5.1), you have to manually convert the [pscustomobject] instance returned by ConvertFrom-Json to a hashtable:

# Load JSON from file 'config.json' into a [pscustomobject] instance.
$paramsAux = Get-Content -Raw config.json | ConvertFrom-Json

# Convert the [pscustomobject] to a [hashtable] instance by 
# making its properties (name-value pairs) hashtable entries.
$params = @{}
foreach ($prop in $paramsAux.psobject.Properties) {
  $params[$prop.Name] = $prop.Value
}

# Use the hashtable for splatting.
New-ADUser @params

The sample config JSON you've provided in a comment indicates that the prerequisites stated at the top are not met, and that custom transformation of the config JSON is required in order to map onto the targeted New-ADUser parameters:

  • Update: The truly intended target cmdlet turned out to be New-AzureADuser, for whose parameters the properties of the sample JSON below are a direct match, so no custom transformation is needed; hopefully, the technique shown is still useful to future readers who do need custom transformations.
# Create a sample JSON config file.
@'
{
  "GivenName": "Lili",
  "SurName": "Waters",
  "accountEnabled": true,
  "displayName": "Lili Waters",
  "mailNickname": "LiliW",
  "userPrincipalName": "liliw@mailcom",
  "passwordProfile": {
    "forceChangePasswordNextSignIn": true,
    "password": "xxyyzz"
  }
}
'@ > config.json

# Load JSON from file 'config.json' into a [pscustomobject] instance.
$paramsAux = Get-Content -Raw config.json | ConvertFrom-Json

# Convert the [pscustomobject] to a [hashtable] instance by 
# making its properties (name-value pairs) hashtable entries,
# applying custom transformations, as necessary.
$params = @{}
foreach ($prop in $paramsAux.psobject.Properties) {
  switch ($prop.Name) {
    # Map the JSON property names and values onto the appropriate 
    # New-ADUser parameters.
    'accountEnabled'  { $params['Enabled'] = $prop.Value }

    'mailNickname'    { $params['SamAccountName'] = $prop.Value  }

    'passwordProfile' { 
      $params['ChangePasswordAtLogon'] = $prop.Value.forceChangePasswordNextSignIn
      $params['AccountPassword'] = ConvertTo-SecureString -Force -AsPlainText $prop.Value.password
     }

    # All other properties directly map onto New-ADUser parameters.
    default           { $params[$prop.Name] = $prop.Value }
  }
}

# Use the hashtable for splatting.
# Note: To inspect the actual arguments being passed, use Write-Output in lieu
#       of New-ADUser, or just output the hashtable, $params, by itself.
New-ADUser @params

Note: I'm unsure as to what parameter the mailNickname property maps to; I've assumed -SamAccountName above; adjust as needed.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • @AshlyneB: That's what the first two code snippets in the answer show, for PowerShell (Core) 7+ and Window PowerShell, respectively. – mklement0 Jul 25 '21 at 07:51
  • @AshlyneB: That's because the `PasswordProfile` property must be an _object_ with properties such as `forceChangePasswordNextSignIn`, not a _string_. The sample JSON you had provided earlier - which is now part of the answer - shows the requisite structure. – mklement0 Jul 25 '21 at 14:17
  • Also note that you cannot perform variable expansion such as `$PasswordProfile` _in JSON text_ - that value is used _as-is_, which is what you're seeing. You can assign an object _after_ having called `ConvertFrom-Json`, with `$param.PasswordProfile = $PasswordProfile`. – mklement0 Jul 25 '21 at 14:20
1

The answer by @mklement0 is great and explains everything. i am stuck in the ps5 world currently, so i have to resort to skipping the -ashashtable option. I thought I'd show a little example of how I do it. This is just a more terse version of what @mklement0 has.

I currently use a oneliner for the conversion like the sql example below:

#get all my settings
$cfg = Get-Content settings.json -Raw | ConvertFrom-Json

#convert the arguments i want to splat
$sqlargs = $cfg.sql.psobject.Properties|%{$h=@{}}{$h."$($_.Name)"=$_.Value}{$h}

#use args as splat
$dt = Invoke-Sqlcmd @sqlargs

and settings.json looks something like...

{
    "sql": {
        "QueryTimeout": 1800,
        "ConnectionString": "my connection string",
        "InputFile": "sqlfile.sql",
        "OutputAs": "DataTables"
    }
}

i have other settings in the file that do i don't need to pass as args, so i don't need to convert the entire file, just this one property for splatting.

i thought about creating a module for this since i use it a bit for various things, but i this project which looks like it would do the trick in that case.

Roy Ashbrook
  • 814
  • 8
  • 14