Access JSON array via PowerShell - json

I'm trying to access a JSON attribute which contains an array of strings, using PowerShell
JSON
{
"id": "00000000-0000-0000-0000-000000000000",
"teamName": "Team A",
"securityGroups": [{
"name": "Security Group 1",
"members:": ["abc#mail.com", "def#mail.com", "ghi#mail.com"]
},
{
"name": "Securiy Group 2",
"members:": ["123#mail.com", "456#mail.com", "789#mail.com"]
}]
}
PowerShell
$json = Get-Content 'test.json' | ConvertFrom-Json
ForEach($group in $json.securityGroups)
{
Write-Host "Team: $($group.name)"
ForEach($member in $group.members)
{
Write-Host "Member: $($member)"
}
}
Output
Team: Security Group 1
Team: Securiy Group 2
As you can see, only the name of the security group (securityGroup.name) gets shown. I'm unable to access the securityGroups.members node, which contains an array of strings (containing emails). My goal is to store this list of strings and loop through them.
When I check to see how the $json object looks like in PS, I get the following:
PS C:\Users\XYZ> $json
id teamName securityGroups
-- -------- --------------
00000000-0000-0000-0000-000000000000 Team A {#{name=Security Group 1; members:=System.Object[]}, #{name=Securiy Group 2; members:=System.Object[]}}
What am I missing here?

You can use this:
$json = Get-Content 'test.json' | ConvertFrom-Json
ForEach ($group in $json.securityGroups)
{
Write-Host "Team: $($group.name)"
ForEach ($member in $group."members:")
{
Write-Host "Member: $($member)"
}
}
You haven't noted that member key contains a colon at the end. Otherwise it will give you wrong result.

Related

Populate collection of objects from one JSON file to the collection of another one with PowerShell

I have two JSON files and want to transfer collection of objects from one file to another. Suppose, the from.json file contains property which represents collection of clients:
"Clients":
[
{
"Name": "Name1",
"Age": "12"
},
{
"Name": "Name2",
"Age": "14"
}
]
to.json file contains an empty collection, "Objects: []" ,which must be filled with objects from from.json. Each objects in toJson variable must contain additional property - Id, so eventually, my "to.json" file should look like this:
"Objects":
[
{
"Id": "{new-id}",
"Name": "Name1",
"Age": "12"
},
{
"Id": "{new-id}",
"Name": "Name1",
"Age": "12"
}
]
I've converted two files into variables:
$fromJson = (Get-Content -Raw -Path {fromPath}) | ConvertFrom-Json
$toJson = (Get-Content -Raw -Path {toPath}) | ConvertFrom-Json
I know that objects from fromJson to toJson can be transferred in the following manner:
toJson.Objects += fromJson.Clients, but that's not enough in my case. I think that it could be done by iterating through fromJson.Clients array but have no idea how to create an object and add it into toJson.Objects collection.
Here's a more efficient solution, based on:
Use of a calculated property with Select-Object, which allows you to place the new property first in the output objects.
Instead of building the array one by one with += (which is inefficient, because a new array must technically be created behind the scenes in every iteration), the solution below lets PowerShell collect the output objects of the Select-Object call in an array automatically (the [array] type constraint is needed to ensure that an array is created even if only one object happens to be output.)
# Sample input.
$fromJson = ConvertFrom-Json '{"Clients":[{"Name":"Name1","Age":"12"},{"Name":"Name2","Age":"14"}]}'
$toJson = ConvertFrom-Json '{ "Objects": [] }'
[array] $toJson.Objects =
$fromJson.Clients |
Select-Object #{ Name='Id'; Expression = { [string] (New-Guid) } }, *
$toJson | ConvertTo-Json -Depth 3 # append | Set-Content as needed.
Kind of new to the PowerShell, but after a bit of investigation came up with the following solution:
fromJson.Clients | ForEach-Object {
$_ | Add-Member -MemberType NoteProperty -Name 'Id' -Value ([guid]::NewGuid().Guid.ToString())
$toJson += $_
}
...
$toJson | ConvertTo-Json | Out-File {to.json_path}
Frankly, don't know if that is a 'proper' way to do that, but generally it works for that particular case. For now, see no other solution.

powershell - iterate over json keys that have similar name

I have a json block containing keys that have a similar name, each is numbered. I want to iterate over those keys. How can this be achieved?
Eg
$json = #"
{
"output": [
{
"AIeventCheck1": "A",
"AIeventCheck2": "B",
"AIeventCheck3": "C"
}
]
}
"#
$config = $json | ConvertFrom-Json
ForEach ($AIeventCheck in $config.output) {
Write-host AIeventCheck value: $AIeventCheck
}
target output:
A
B
C
Use the psobject memberset to access the individual properties of the object(s):
foreach($AIeventCheck in $config.output){
$AIEventCheckValues = $AIEventCheck.psobject.Properties |Where Name -like 'AIeventCheck*' |ForEach-Object Value
Write-Host AIeventCheck value: $AIeventCheckValues
}

Reading a json file in key value pair in the same order that's given in input

I am writing a PowerShell Script, which will read a json file having different sections, like job1, job2 and so on.. Now my objective is to read each section separately and to loop through it as a key value pair. I also need to maintain the order of the input file, because the jobs are scheduled in sequence. and these jobs run taking the values from the json file as input.
I tried using Powershell version 5.1, in which I created PSCustomObject but the order is getting sorted alphabetically, which I DON'T want.
Json File :
{ "Job1": [
{
"Ram" : "India",
"Anthony" : "London",
"Elena" : "Zurich"
}],
"Job2": [
{
"Build" : "fail",
"Anthony" : "right",
"Sam" : "left"
}]}
$json = Get-Content -Path C:\PowershellScripts\config_File.json |
ConvertFrom-Json
$obj = $json.Job1
$json.Job1 | Get-Member -MemberType NoteProperty | ForEach-Object {
$key = $_.Name
$values = [PSCustomObject][ordered]#{Key = $key; Value = $obj."$key"}
$values
}
I am expecting to loop through each section separately and in the same order that's provided in the json file. For example looping through Job1 section and to fetch only the Values in the same order that's in the json file.
I will guarantee that this is not the best way to do this, but it works.
$json = Get-Content -Path C:\PowershellScripts\config_File.json |
ConvertFrom-Json
$out = ($json.Job1 | Format-List | Out-String).Trim() -replace "\s+(?=:)|(?<=:)\s+"
$out -split "\r?\n" | ForEach-Object {
[PSCustomObject]#{Key = $_.Split(":")[0]; Value = $_.Split(":")[1]}
}
Explanation:
The JSON object is first output using Format-List to produce the Property : Value format, which is piped to Out-String to make that output a single string. Trim() is used to remove surrounding white space.
The -replace removes all white space before and after : characters.
The -split \r?\n splits the single string into an array of lines. Each of those lines is then split by the : character (.Split(":")). The [0] index selects the string on the left side of the :. The [1] selects the string on the right side of the :.
Can you change the json schema?
I would probably make changes to the json schema before i tried to parse this (if possible of course).
Like this (changed only Job1):
$json = #"
{ "Job1": [
{
"Name": "Ram",
"Location" : "India"
},
{
"Name": "Anthony",
"Location": "London"
},
{
"Name": "Elena" ,
"Location": "Zurich"
}
],
"Job2": [
{
"Build" : "fail",
"Anthony" : "right",
"Sam" : "left"
}]}
"# | convertfrom-json
foreach ($obj in $json.Job1) {
$key = $obj.Name
$values = [PSCustomObject][ordered]#{Key = $key; Value = $obj."$key" }
$values
}

How do I select specific data from a PowerShell object sourced from JSON data?

I have imported some JSON data and converted it to a PowerShell Object. I would like to understand how to retrieve specific portions of said data.
test.json:
{
"Table": {
"Users": {
"Columns": [ "[Id]",
"[FName]",
"[MName]",
"[SName]",
"[UName]",
"[Pasword]" ],
"data": "CustomUserData"
},
"Roles": {
"Columns": [ "[Id]",
"[Role]",
"[Description]" ],
"data": "CustomRoleData"
}
}
}
Import to PS Object:
$userdata = Get-Content .\test.json |ConvertFrom-Json
Retrieve and format column data:
PS> $userdata = Get-Content ./test.json |ConvertFrom-Json
PS> $columns = $userdata.Table.Users.Columns -join ","
PS> $columns
[Id],[FName],[MName],[SName],[UName],[Pasword]
Example retrieval of custom data:
PS> $userdata.Table.Users.data
CustomUserData
What I would like to do is:
Select just the table names. When I try and do this by calling $userdata.table I get the following:
PS> $userdata.Table |Format-List
Users : #{Columns=System.Object[]; data=CustomUserData}
Roles : #{Columns=System.Object[]; data=CustomRoleData}
What I am looking for is just a list of the table names, in this case - Users,Roles
I would also like to know how to leverage this to create a ForEach loop which cycles through each table name and prints the columns associated with each table - ultimately I will be using this to craft a SQL query.
Thank you!
Maybe this can help you.
It is a small function to output the property names recursively.
function Get-Properties($obj, [int]$level = 0) {
$spacer = " "*$level
$obj.PSObject.Properties | ForEach-Object {
$spacer + $_.Name
if ($_.Value -is [PSCustomObject]){
Get-Properties $_.Value ($level + 2)
}
}
}
In your case, you can use it like this:
$userdata = Get-Content ./test.json | ConvertFrom-Json
Get-Properties $userData
The console output will look like this:
Table
Users
Columns
data
Roles
Columns
data

Create a Specific JSON file from csv in PowerShell

I have no experience with PowerShell and I was asked to create this script as a favor for a friend of mine. The script is supposed to read a csv file (These files have different columns except for time and host, which are common among all files), and output its content into a JSON file of the following format:
CSV file contains columns:
host| message | time | severity | source |
{
"time": 1437522387,
"host": "dataserver992.example.com",
"event": {
"message": "Something happened",
"severity": "INFO",
"source": "testapp"
#...All columns except for time and host should be under "event"
}
}
*The only guaranteed columns are time and host. All other column headers vary from file to file.
This is part of what I have so far:
$csvFile = Import-Csv $filePath
function jsonConverter($file)
{
#Currently not in use
$eventString = $file| select * -ExcludeProperty time, host
$file | Foreach-Object {
Write-Host '{'
Write-Host '"host":"'$_.host'",'
Write-Host '"time":"'$_.time'",'
Write-Host '"event":{'
#TODO: Put all other columns (key, values) under event - Except for
time and host
Write-Host '}'
}
}
jsonConverter($csvFile)
Any ideas of how I could extract only the remaining columns, row by row, outputting its content to a key, value JSON format like the example above?
Thank you!
Provided your csv looks like this:
"host","message","time","severity","source"
"dataserver992.example.com","Something happened","1437522387","INFO","testapp"
this script:
$filepath = '.\input.csv'
$csvData = Import-Csv $filePath
$NewCsvData = foreach($Row in $csvData){
[PSCustomObject]#{
time = $Row.time
host = $Row.host
event = ($Row| Select-Object -Property * -ExcludeProperty time,host)
}
}
$NewCsvData | ConvertTo-Json
will output this Json:
{
"time": "1437522387",
"host": "dataserver992.example.com",
"event": {
"message": "Something happened",
"severity": "INFO",
"source": "testapp"
}
}
If your powershell version is 3.0 or higher (it should):
Import-CSV $filepath | ConvertTo-JSON
Done!