How to read JSON data from Powershell script and iterate through it - json

I'm starting to learn Powershell and I'm currently trying to read in a JSON file.
Here is my JSON file (named 'versions.json'):
{
"versions": {
"1.0.0": {
"Component1": "1.0.0",
"Component2": "1.0.0",
"Component3": "1.0.0",
},
"2.0.0": {
"Component1": "2.0.0",
"Component2": "2.0.0",
"Component3": "2.0.0"
}
}
}
I would like to read in this JSON file and print out the versions and what they consist of. For example, 1.0.0 consists of Component 1 at 1.0.0, Component 2 at 1.0.0, and Component 3 at 1.0.0.
I'm currently reading in the JSON file with this Powershell line:
$json = (Get-Content "versions.json" -Raw) | ConvertFrom-Json
Now, I want to iterate through $json and print out its data. I'm currently using this:
foreach($v in $json.versions) {
echo "Data: $v"
}
But, when I run my Powershell script, it prints:
Data: #{1.0.0=; 2.0.0=}
Is this the proper output? I was expecting to at least see two entries for 1.0.0 and 2.0.0. This feels like it may be a syntax issue but I am unsure. I am using Powershell version 5.

After using ConvertFrom-Json you have a PowerShell object which is a single item that has a versions property which has two sub-properties 1.0.0 and 2.0.0. Your ForEach is attempting to iterate them like a collection, but its just a single object.
However you can iterate over the properties as follows to get the result I think you wanted:
($Json.versions.psobject.properties) | foreach-object { "Data: $($_.name)" }

Related

Is there a way to split json data from a file in powershell?

I am reading data from a json file via powershell, with the ultimate goal of updating said file. I need to split the data in a chunk I want to keep and a chunk I want to update, and to complicate the matter further, the place where I need to split the text varies throughout a foreach-loop, thus I need that part to come from a variable.
I have tried .split/-split and .replace/-replace in numerous configurations, but it seems this is harder than one would assume in powershell.
All the below files in the same folder.
Json (json.json):
{
"Section1": {
"Heading1": [
"Thing1",
"Thing2"
]
},
"Section2": [
"Thing1",
"Thing2"
]
}
Powershell (powershell.ps1):
$originalJsonString = Get-Content -Path ".\json.json"
$SplitTarget = "Section2"
$JsonString = {This is the part that I am iffy about}
Write-Output $JsonString
The output I want from the above would be
{
"Section1": {
"Heading1": [
"Thing1",
"Thing2"
]
},
I have tried just about everything I can think of in relation to split and replace, but yet the solution alludes me.
Note in the solution above, that it is an important factor that $originalJsonString is split (or whatever) by $SplitTarget, and not "Section2", as that is also a factor in my equation.
This is my first time asking, so if I am doing something wrong I apologise.
Thank you.
Edit:
It is only fair that I add the reason I don't convert to an object.
The syntax which powershell exports when converting json to an object and back is undesirable for my use.
However, if using an object is the ONLY way, and slitting is out of the question, then another solution must be found.
Thank you.
Edit:
If objects was the way to go, I ended up finding a way more complicated way to format the .json the way I wanted it.
Thanks everyone.
What you should do is read the json file in using :
$json = Get-Content .\json.json -raw | ConvertFrom-Json
I faked that here using a 'here-string':
$json = #"
{
"Section1": {
"Heading1": [
"Thing1",
"Thing2"
]
},
"Section2": [
"Thing1",
"Thing2"
]
}
"# | ConvertFrom-Json
Next, define what you want to keep or update:
$sectionToKeep = "Section1"
$sectionToUpdate = "Section2"
To see what is in there use $json.$sectionToKeep | ConvertTo-Json
{
"Heading1": [
"Thing1",
"Thing2"
]
}
Next, update $section2 leaving everything else untouched. I am writing an object that stores an array, just like in $sectionToKeep:
$json.$sectionToUpdate = #{'Heading2' = 'Thing3', 'Thing4'}
and finally output (or write back to file) the new complete json:
$json | ConvertTo-Json
Using your example gives you this:
{
"Section1": {
"Heading1": [
"Thing1",
"Thing2"
]
},
"Section2": {
"Heading2": [
"Thing3",
"Thing4"
]
}
}
Hope that helps
Not sure to really understand your question, but I would convert the Json to an object and then filter the sub data and create a file again
$obj = Get-Content json.json -raw | ConvertFrom-Json
If you are looking to just isolate a section and create a new json file, then you can use the following:
$file = Get-Content .\json.json | ConvertFrom-Json
$file | Select-Object Section1 | ConvertTo-Json | Set-Content New.json

Iterate through json custom object

I'm trying to perform some config transformations on JSON files using PowerShell.
For this there's several input json files and a transform one (one for each environment).
Input sample (AzureStorage.json):
{
"$schema": "http://datafactories.schema.management.azure.com/schemas/2015-09-01/Microsoft.DataFactory.LinkedService.json",
"name": "AzureStorage",
"properties": {
"type": "AzureStorage",
"typeProperties": {
"connectionString": "My Connection String here"
} } }
Transform:
{
"$schema": "http://datafactories.schema.management.azure.com/vsschemas/V1/Microsoft.DataFactory.Config.json",
"AzureStorage": [
{
"name": "$.properties.typeProperties.connectionString",
"value": "DefaultEndpointsProtocol=https;AccountName=mytestaccount;AccountKey=d;lasfjdalfdjfldjfdsfds;EndpointSuffix=core.windows.net"
}
],
"DataLakeStore": [
{
"name": "$.properties.typeProperties.dataLakeStoreUri",
"value": "https://mydatalake.azuredatalakestore.net/webhdfs/v1"
}
]
}
What I need to do, is to load the transform file, then traverse it, finding the names of the input files I need to transform (in this example AzureStorage.json and DataLakeStore.json).
Next, I need to replace the properties accordingly. I'm trying to do it by loading the transform file into a variable using ConvertFrom-Json, but I not sure how to traverse it afterwards.
I don't know hat exactly you need. I'm guessing access to the information within the JSON file.
What about this approach?
$json_object = Get-Content -Raw -Path '<your_path>\transform.json' | ConvertFrom-Json
$azure_storage = #('AzureStorage'; 'DataLakeStore')
ForEach ($azure in $json_object) {
ForEach ($storage in $azure_storage) {
Write-Output $azure.$storage.name
Write-Output $azure.$storage.value
}
}
Edit Due to edit I got it. You need a generic access.
Here you go:
$json_object = (Get-Content -Path '<your_path>\transform.json') -join "`n" | ConvertFrom-Json
ForEach ($object in $json_object.PsObject.Properties) {
Write-Output $object.name
Write-Output $object.value
}
Explanation:
(Get-Content -Path '<your_path>\transform.json') -join "n"` is a Microsoft's MSDN recommended way to read json files.
You need to find out where the values are. The object you are using is a "Windows PowerShell custom object" - PsObject. To access the you need to use .Properties.value. Then you have the Strings you want and you can access them using .name and .value.

Pass bash variable (string) as jq argument to walk JSON object

This is seemingly a very basic question. I am new to JSON, so I am prepared for the incoming facepalm.
I have the following JSON file (test-app-1.json):
"application.name": "test-app-1",
"environments": {
"development": [
"server1"
],
"stage": [
"server2",
"server3"
],
"production": [
"server4",
"server5"
]
}
The intent is to use this as a configuration file and reference for input validation.
I am using bash 3.2 and will be using jq 1.4 (not the latest) to read the JSON.
The problem:
I need to return all values in the specified JSON array based on an argument.
Example: (how the documentation and other resources show that it should work)
APPLICATION_ENVIRONMENT="developement"
jq --arg appenv "$APPLICATION_ENVIRONMENT" '.environments."$env[]"' test-app-1.json
If executed, this returns null. This should return server1.
Obviously, if I specify text explicitly matching the JSON arrays under environment, it works just fine:
jq 'environments.development[]' test-app-1.json returns: server1.
Limitations: I am stuck to jq 1.4 for this project. I have tried the same actions in 1.5 on a different machine with the same null results.
What am I doing wrong here?
jq documentation: https://stedolan.github.io/jq/manual/
You have three issues - two typos and one jq filter usage issue:
set APPLICATION_ENVIRONMENT to development instead of developement
use variable name consistently: if you define appenv, use $appenv, not $env
address with .environments[$appenv]
When fixed, looks like this:
$ APPLICATION_ENVIRONMENT="development"
$ jq --arg appenv "$APPLICATION_ENVIRONMENT" '.environments[$appenv][]' test-app-1.json
"server1"

How to get the list of application names and uninstall strings from JSON file and pass them as parameters to uninstall an application using powershell

I would like to read JSON file to get the list of application names and their respective uninstall strings and pass them as arguments in power shell to uninstall the apps irrespective of whether the apps are Windows Installer(MSI) or setup. Can someone please suggest me how to do this. Thanks
Use the ConvertFrom-JSON.
This will create a PSObject out of the JSON
$TEST2 = $TEST | ConvertFrom-Json
Thank you for suggesting the answer, that worked. I used the following cmd-line
$J = Get-Content -Raw -Path $scriptDirectory\Files\XXX.json | ConvertFrom-Json
and passed the AppName property as given below to fetch the application names:
$AppName = $J |fl -Property AppName.
FYI.. my JSON file content looked as follows:
[
{
"AppName": "xxxxx",
"AppVersion": "aa.bb"
},
{
"AppName": "yyy",
"AppVersion": "aa.bb.cc"
}
]

Need help! - Unable to load JSON using COPY command

Need your expertise here!
I am trying to load a JSON file (generated by JSON dumps) into redshift using copy command which is in the following format,
[
{
"cookieId": "cb2278",
"environment": "STAGE",
"errorMessages": [
"70460"
]
}
,
{
"cookieId": "cb2271",
"environment": "STG",
"errorMessages": [
"70460"
]
}
]
We ran into the error - "Invalid JSONPath format: Member is not an object."
when I tried to get rid of square braces - [] and remove the "," comma separator between JSON dicts then it loads perfectly fine.
{
"cookieId": "cb2278",
"environment": "STAGE",
"errorMessages": [
"70460"
]
}
{
"cookieId": "cb2271",
"environment": "STG",
"errorMessages": [
"70460"
]
}
But in reality most JSON files from API s have this formatting.
I could do string replace or reg ex to get rid of , and [] but I am wondering if there is a better way to load into redshift seamlessly with out modifying the file.
One way to convert a JSON array into a stream of the array's elements is to pipe the former into jq '.[]'. The output is sent to stdout.
If the JSON array is in a file named input.json, then the following command will produce a stream of the array's elements on stdout:
$ jq ".[]" input.json
If you want the output in jsonlines format, then use the -c switch (i.e. jq -c ......).
For more on jq, see https://stedolan.github.io/jq