Iterate over json Array using Power shell - json

This is what I have tried so far:
$Path="C:\Users\Desktop\test.json"
$json=(Get-Content $Path | ConvertFrom-Json).parameters.FileArray
//FileArray is array name in json file
$demo=$json.GetType().FullName //System.Object[]
foreach($file in Get-ChildItem "D:\A\DF\ls\" -Include $json|ForEach Object{$_} -Recurse){
Write-Output $file.BaseName
Write-Output $file.FullName
Set-AzureRmDataFactoryV2LinkedService -DataFactoryName "adfg1" - ResourceGroupName "bgc" -Name $file.BaseName -DefinitionFile $file.FullName -Force
}
Json I am using test.json:
{
"parameters":
{
"FileArray": [
"ABC.json",
"DEF.json"]
}
}
Exception I am getting is:
ForEach-Object : Cannot bind parameter 'RemainingScripts'. Cannot convert
the "-Recurse" value of type "System.String" to
type "System.Management.Automation.ScriptBlock".
What I am expecting(Names of files):
ABC.json
DEF.json
Any help how it can be handled.
How I can iterate over array values from json.
P.S: I am beginner in powershell

foreach($file in (Get-ChildItem "D:\A\DF\ls\" -Include $json -Recurse)) {
$file.BaseName
$file.FullName
}
I don't see why you would need ForEach Object{$_} , the -include accepts an array
Example code:
$jsonfile = '{"parameters":
{ "FileArray": [ "ABC.json", "DEF.json"] } }' | ConvertFrom-Json
$json = $jsonfile.parameters.FileArray
foreach($file in (Get-ChildItem "c:\temp" -Include $json -Recurse)) {
$file.BaseName
$file.FullName
}
Example output:
ABC
C:\temp\example-folder\ABC.json
DEF
C:\temp\example-folder\DEF.json

Related

Easy way to reference JSON arrays [duplicate]

I want to get a JSON representation of a Hashtable such as this:
#{Path="C:\temp"; Filter="*.js"}
ConvertTo-Json results in:
{
"Path": "C:\\temp",
"Filter": "*.js"
}
However, if you convert that JSON string back with ConvertFrom-Json you don't get a HashTable but a PSCustomObject.
So how can one reliably serialize the above Hashmap?
$json = #{Path="C:\temp"; Filter="*.js"} | ConvertTo-Json
$hashtable = #{}
(ConvertFrom-Json $json).psobject.properties | Foreach { $hashtable[$_.Name] = $_.Value }
Adapted from PSCustomObject to Hashtable
A little late to the discussion here, but in PowerShell 6 (Core) there is a -AsHashtable parameter in ConvertFrom-Json.
JavaScriptSerializer is available since .NET3.5 (may be installed on XP, included in Win7 and newer), it's several times faster than Convert-FromJSON and it properly parses nested objects, arrays etc.
function Parse-JsonFile([string]$file) {
$text = [IO.File]::ReadAllText($file)
$parser = New-Object Web.Script.Serialization.JavaScriptSerializer
$parser.MaxJsonLength = $text.length
Write-Output -NoEnumerate $parser.DeserializeObject($text)
}
The answer for this post is a great start, but is a bit naive when you start getting more complex json representations.
The code below will parse nested json arrays and json objects.
[CmdletBinding]
function Get-FromJson
{
param(
[Parameter(Mandatory=$true, Position=1)]
[string]$Path
)
function Get-Value {
param( $value )
$result = $null
if ( $value -is [System.Management.Automation.PSCustomObject] )
{
Write-Verbose "Get-Value: value is PSCustomObject"
$result = #{}
$value.psobject.properties | ForEach-Object {
$result[$_.Name] = Get-Value -value $_.Value
}
}
elseif ($value -is [System.Object[]])
{
$list = New-Object System.Collections.ArrayList
Write-Verbose "Get-Value: value is Array"
$value | ForEach-Object {
$list.Add((Get-Value -value $_)) | Out-Null
}
$result = $list
}
else
{
Write-Verbose "Get-Value: value is type: $($value.GetType())"
$result = $value
}
return $result
}
if (Test-Path $Path)
{
$json = Get-Content $Path -Raw
}
else
{
$json = '{}'
}
$hashtable = Get-Value -value (ConvertFrom-Json $json)
return $hashtable
}
I believe the solution presented in Converting JSON to a hashtable is closer to the PowerShell 6.0 implementation of ConvertFrom-Json
I tried with several JSON sources and I always got the right hashtable.
$mappings = #{
Letters = (
"A",
"B")
Numbers = (
"1",
"2",
"3")
Yes = 1
False = "0"
}
# TO JSON
$jsonMappings = $mappings | ConvertTo-JSON
$jsonMappings
# Back to hashtable
# In PowerShell 6.0 would be:
# | ConvertFrom-Json -AsHashtable
$jsonMappings | ConvertFrom-Json -As hashtable
you can write a function convert psobject to hashtable.
I wrote a answer here:enter link description here

PowerShell JSON adding value format

I am adding data to a json file. I do this by
$blockcvalue =#"
{
"connectionString":"server=(localdb)\\mssqllocaldb; Integrated Security=true;Database=$database;"
}
"#
$ConfigJson = Get-Content C:\Users\user\Desktop\myJsonFile.json -raw | ConvertFrom-Json
$ConfigJson.data | add-member -Name "database" -value (Convertfrom-Json $blockcvalue) -MemberType NoteProperty
$ConfigJson | ConvertTo-Json| Set-Content C:\Users\user\Desktop\myJsonFile.json
But the format comes out like this:
{
"data": {
"database": {
"connectionString": "server=(localdb)\\mssqllocaldb; Integrated Security=true;Database=mydatabase;"
}
}
}
but I need it like this:
{
"data": {
"database":"server=(localdb)\\mssqllocaldb; Integrated Security=true;Database=mydatabase;"
}
}
}
Can someone help please?
Here's my function to prettify JSON output:
function Format-Json {
<#
.SYNOPSIS
Prettifies JSON output.
.DESCRIPTION
Reformats a JSON string so the output looks better than what ConvertTo-Json outputs.
.PARAMETER Json
Required: [string] The JSON text to prettify.
.PARAMETER Indentation
Optional: The number of spaces to use for indentation. Defaults to 2.
.PARAMETER AsArray
Optional: If set, the output will be in the form of a string array, otherwise a single string is output.
.EXAMPLE
$json | ConvertTo-Json | Format-Json -Indentation 4
#>
[CmdletBinding()]
Param(
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
[string]$Json,
[int]$Indentation = 2,
[switch]$AsArray
)
# If the input JSON text has been created with ConvertTo-Json -Compress
# then we first need to reconvert it without compression
if ($Json -notmatch '\r?\n') {
$Json = ($Json | ConvertFrom-Json) | ConvertTo-Json -Depth 100
}
$indent = 0
$Indentation = [Math]::Abs($Indentation)
$regexUnlessQuoted = '(?=([^"]*"[^"]*")*[^"]*$)'
$result = $Json -split '\r?\n' |
ForEach-Object {
# If the line contains a ] or } character,
# we need to decrement the indentation level unless it is inside quotes.
if ($_ -match "[}\]]$regexUnlessQuoted") {
$indent = [Math]::Max($indent - $Indentation, 0)
}
# Replace all colon-space combinations by ": " unless it is inside quotes.
$line = (' ' * $indent) + ($_.TrimStart() -replace ":\s+$regexUnlessQuoted", ': ')
# If the line contains a [ or { character,
# we need to increment the indentation level unless it is inside quotes.
if ($_ -match "[\{\[]$regexUnlessQuoted") {
$indent += $Indentation
}
$line
}
if ($AsArray) { return $result }
return $result -Join [Environment]::NewLine
}
Use it like so:
$ConfigJson | ConvertTo-Json | Format-Json | Set-Content C:\Users\user\Desktop\myJsonFile.json
Replace
(Convertfrom-Json $blockcvalue)
with
(Convertfrom-Json $blockcvalue).connectionString
Then your output object's data.database property will directly contain the "server=(localdb)\\..." value, as desired, not via a nested object that has a connectionString property.
There is one simple Newtonsoft.Json Parser which makes it rly simple to get required format:
Import-Module Newtonsoft.Json
$path = "C:\..."
$json = Get-Content -Path $path -Raw
$parsedJson = [Newtonsoft.Json.Linq.JToken]::Parse($json);
Set-Content $path $parsedJson.ToString();
Enjoy ;)

start-process issue with json contents

Contents of .js file. Program.js
[
{ "ProgramName":"Chrome", "FilePath":"\"\\\\PCNAME\\c$\\Users\\USERNAME\\Desktop\\Work Notes\\Programs\\Google\\ChromeSetup.exe\""},
{ "ProgramName":"Notepad ++", "FilePath":"\"\\\\PCNAME\\c$\\Users\\USERNAME\\Desktop\\Work Notes\\Programs\\Notepad ++\\npp.7.3.3.Installer.exe\"" }
]
I'm bad at explaining but I'm trying to get the ProgramName for each line of the json file and if the name matches one of the names in the $computernames array. Then use the corresponding FilePath of the programname to run the installer.
This is what I have so far.
$json = (Get-Content "\\PCNAME\c$\Users\USERNAME\Desktop\Powershell\SCCM\Softwareinstaller\Program.js" -Raw) | ConvertFrom-Json
$computerNames = "Chrome","Office","Google Earth","Adobe Pro","GoToMeeting Opener"
foreach ($thing in $json)
{
foreach ($thing2 in $json)
{
if ($computernames -contains $Thing2.programname)
{
Start-Process -filepath $thing.FilePath -wait
}
}
}
I plan on adding more to the json file so a method that doesn't look for just the line number would be preferred.
I'm not sure why you have the thing2-loop. Your JSON is an array of items. Run a loop, see if the name is in your $computerNames-array (bad name btw.) and execute. Try:
$json = (Get-Content "\\PCNAME\c$\Users\USERNAME\Desktop\Powershell\SCCM\Softwareinstaller\Program.js" -Raw) | ConvertFrom-Json
$computerNames = "Chrome","Office","Google Earth","Adobe Pro","GoToMeeting Opener"
foreach ($thing in $json)
{
if ($computernames -contains $thing.ProgramName)
{
Start-Process -FilePath $thing.FilePath -wait
}
}

Access Object From JSON File in Powershell

I have a JSON file that I am reading in Powershell. The structure of the file is below.
[
["computer1", ["program1", versionX]],
["computer2", ["program2", versionY]],
["computer3", ["program3", "versionX"],
["program1", "versionZ"]
],
]
What I want in the program is use $env:computername and compare it with the computerX in the JSON file. If found a match, then iterate through and get the values of programName and ProgramVersion.
However, I don't know how to search through the objects and find ALL items under that.
This is what I have so far.
$rawData = Get-Content -Raw -Path "file.json" | ConvertFrom-Json
$computername=$env:computername
$data = $rawData -match $computername
This gives me objects under it. But how do I iterate through and get individual values?
But don't know what I do after that.
To start you need to be using a valid JSON file
{
"computer1": {
"program1": "versionX"
},
"computer2": {
"program2": "versionY"
},
"computer3": {
"program3": "versionX",
"program1": "versionZ"
}
}
Then you can access the PSObject Properties
$rawData = Get-Content -Raw -Path "file.json" | ConvertFrom-Json
$rawData.PsObject.Properties |
Select-Object -ExpandProperty Name |
ForEach-Object { IF ($_ -eq $env:COMPUTERNAME) {
Write-Host "Computer Name : " $_
Write-Host "Value : " $rawData."$_"
}
}
EDIT for Computer, Program, and Version as separate values
psobject.Properties.Name will give all the program names.
psobject.Properties.Name[0] will give the first program name.
psobject.Properties.value[0] will give the first program version value.
You need to increment the value to get second value, you can also use -1 as a shortcut for the last value.
$rawData = Get-Content -Raw -Path "file.json" | ConvertFrom-Json
$rawData.PsObject.Properties |
Select-Object -ExpandProperty Name |
ForEach-Object { IF ($_ -eq $env:COMPUTERNAME) {
$Computer = $_
$Values = $rawData.$_
}
}
$Computer
$Values.psobject.Properties
$Values.psobject.Properties.Name
$Values.psobject.Properties.Name[0]
$Values.psobject.Properties.value[0]
$Values.psobject.Properties.Name[1]
$Values.psobject.Properties.value[1]
You could also use the program name
$Values.program1
$Values.program2
$Values.program3

Create Hashtable from JSON

I want to get a JSON representation of a Hashtable such as this:
#{Path="C:\temp"; Filter="*.js"}
ConvertTo-Json results in:
{
"Path": "C:\\temp",
"Filter": "*.js"
}
However, if you convert that JSON string back with ConvertFrom-Json you don't get a HashTable but a PSCustomObject.
So how can one reliably serialize the above Hashmap?
$json = #{Path="C:\temp"; Filter="*.js"} | ConvertTo-Json
$hashtable = #{}
(ConvertFrom-Json $json).psobject.properties | Foreach { $hashtable[$_.Name] = $_.Value }
Adapted from PSCustomObject to Hashtable
A little late to the discussion here, but in PowerShell 6 (Core) there is a -AsHashtable parameter in ConvertFrom-Json.
JavaScriptSerializer is available since .NET3.5 (may be installed on XP, included in Win7 and newer), it's several times faster than Convert-FromJSON and it properly parses nested objects, arrays etc.
function Parse-JsonFile([string]$file) {
$text = [IO.File]::ReadAllText($file)
$parser = New-Object Web.Script.Serialization.JavaScriptSerializer
$parser.MaxJsonLength = $text.length
Write-Output -NoEnumerate $parser.DeserializeObject($text)
}
The answer for this post is a great start, but is a bit naive when you start getting more complex json representations.
The code below will parse nested json arrays and json objects.
[CmdletBinding]
function Get-FromJson
{
param(
[Parameter(Mandatory=$true, Position=1)]
[string]$Path
)
function Get-Value {
param( $value )
$result = $null
if ( $value -is [System.Management.Automation.PSCustomObject] )
{
Write-Verbose "Get-Value: value is PSCustomObject"
$result = #{}
$value.psobject.properties | ForEach-Object {
$result[$_.Name] = Get-Value -value $_.Value
}
}
elseif ($value -is [System.Object[]])
{
$list = New-Object System.Collections.ArrayList
Write-Verbose "Get-Value: value is Array"
$value | ForEach-Object {
$list.Add((Get-Value -value $_)) | Out-Null
}
$result = $list
}
else
{
Write-Verbose "Get-Value: value is type: $($value.GetType())"
$result = $value
}
return $result
}
if (Test-Path $Path)
{
$json = Get-Content $Path -Raw
}
else
{
$json = '{}'
}
$hashtable = Get-Value -value (ConvertFrom-Json $json)
return $hashtable
}
I believe the solution presented in Converting JSON to a hashtable is closer to the PowerShell 6.0 implementation of ConvertFrom-Json
I tried with several JSON sources and I always got the right hashtable.
$mappings = #{
Letters = (
"A",
"B")
Numbers = (
"1",
"2",
"3")
Yes = 1
False = "0"
}
# TO JSON
$jsonMappings = $mappings | ConvertTo-JSON
$jsonMappings
# Back to hashtable
# In PowerShell 6.0 would be:
# | ConvertFrom-Json -AsHashtable
$jsonMappings | ConvertFrom-Json -As hashtable
you can write a function convert psobject to hashtable.
I wrote a answer here:enter link description here