ConvertFrom-JSON strips array from object - json

I'm loading a text file containing some Json to edit a property. However, after modifying the content and writing it to file, the Json becomes invalid.I
I use the following PowerShell to modify the file:
$manifest = Get-Content $PathToManifest -Raw | ConvertFrom-Json
#modify Json
Set-Content -Path $PathToManifest -Value ( $manifest | ConvertTo-Json)
The following snippet from my Json file gets corrupted:
"contributions": [
{
"id": "sample-data-widget",
"type": "ms.vss-dashboards-web.widget",
"targets": ["ms.vss-dashboards-web.widget-catalog"],
"properties": "#{name=Sample Data; description=Create sample data in a VSTS project.; previewImageUrl=img/logo.png; uri=index.html; supportedSizes=System.Object[]; supportedScopes=System.Object[]}"
}]
After loading the Json and writing it back to file the array syntax around targets is gone:
"contributions": [
{
"id": "sample-data-widget",
"type": "ms.vss-dashboards-web.widget",
"targets": "ms.vss-dashboards-web.widget-catalog",
"properties": "#{name=Sample Data; description=Create sample data in a VSTS project.; previewImageUrl=img/logo.png; uri=index.html; supportedSizes=System.Object[]; supportedScopes=System.Object[]}"
}]
Why is this happening? Is there a way to make sure the syntax doesn't change?

ConvertTo-Json has Depth parameter that controls how many levels of contained objects are included in the JSON representation. The default value is 2. ConvertTo-Json will call .ToString() on anything nested deeper than specified Depth.
So all you need is to specify sufficiently large number for Depth argument or just ([int]::MaxValue).
Set-Content -Path $PathToManifest -Value ( $manifest | ConvertTo-Json -Depth ([int]::MaxValue))
Examples of nesting and ConvertTo-Json behavior:
$NestedArray = #(1,#(2,#(3,#(4))))
Default:
$NestedArray | ConvertTo-Json
[
1,
{
"value": [
2,
[
3,
"4"
]
],
"Count": 2
}
]
No nesting at all:
$NestedArray | ConvertTo-Json -Depth 1
[
1,
{
"value": [
2,
"3 System.Object[]"
],
"Count": 2
}
]
Desired result:
$NestedArray | ConvertTo-Json -Depth 3
[
1,
{
"value": [
2,
[
3,
[
4
]
]
],
"Count": 2
}
]

Related

Extract Value from JSON Using PowerShell based on condition

I have the captured the JSON response in variable $releaseDefinitions. With this i want to extract the "ID" as "4598" when i pass the "name" as "STAGE1-PG-DB" under the "environments" tag using the powershell.
Any help on this is much appreciated.
{
"id": 516,
"environments": [
{
"id": 4598,
"releaseId": 516,
"name": "STAGE1-PG-DB",
"status": "notStarted",
},
{
"id": 4599,
"releaseId": 516,
"name": "STAGE2-PG-DB",
"status": "notStarted",
},
{
"id": 4600,
"releaseId": 516,
"name": "STAGE3-PG-DB",
"status": "notStarted",
}
]
}
I believe you are asking to get the JSON array object where the name is "STAGE1-PG-DB".
Based on the info you've provided, you would do something like this (see my in-line comments)
$releaseDefinitions = Get-Content -Path $inputFileName -Raw | ConvertFrom-Json
# use dot-notation to get the entire Environments array
# pipe the array through using the pipe character
# filter through the array where the key (Name) is equal to your value (STAGE1-PG-DB)
$releaseDefinitions.environments | Where-Object {$_.name -eq "STAGE1-PG-DB"}

trouble parsing json in powershell

I have the below JSON which is just a bit of the file but illustrates it.
I am not that experienced with JSON and I have tried a lot of the examples that I could find but they only seem to show JSON that is just key/value pairs. I've seen a few to target arrays but I cant translate them to my particular JSON
for example I'm trying to get that the 'SavedPlayerDataVersion' is equal to 8 into a variable and I've put it into an object but I cant figure out how to target that particular item within the array and object
could anyone point me in the right direction please?
Thank you
{
"profileVersion": 1,
"profile": {
"id": 0,
"class": "PrimalPlayerDataBP_C",
"names": ["PrimalPlayerDataBP_C_29", "ArkGameMode", "PersistentLevel", "Aberration_P", "/Game/Maps/Aberration/Aberration_P"],
"properties": [{
"name": "SavedPlayerDataVersion",
"type": "IntProperty",
"value": 8
}, {
"name": "HexagonCount",
"type": "IntProperty",
"value": 106860
}, {
"name": "MyPersistentBuffDatas",
"type": "ArrayProperty",
"arrayType": "ObjectProperty",
"value": [1, 2, 3, 4]
}],
"extra": null
}
}
"type": "IntProperty",
"value": 8
}, {
"name": "HexagonCount",
"type": "IntProperty",
"value": 6800
}, {
"name": "NumChibiLevelUpsData",
"type": "IntProperty",
"value": 2
}, {
"name": "MyData",
"type": "StructProperty",
"structType": "PrimalPlayerDataStruct",
"value": [{
"name": "PlayerDataID",
"type": "UInt64Property",
"value": 656195017
}, {
"name": "UniqueID",
"type": "StructProperty",
"structType": "UniqueNetIdRepl",
"value": {
"unk": 8,
"netId": "76561198046328344"
}
}
I have edited the question after the original answers as I realised that what I also needed to access was a 'level' deeper. so it would be getting at "PlayerDataID"
I tried $value = ($jsonobj.profile.properties.mydata | Where-Object { $_.name -eq "PlayerDataID" }).value but that isnt getting it for me
JSON is exactly key-value pairs, so handling it like an object in PowerShell is the way to go. Start with ConvertFrom-Json and put the result in a variable, let's say $myJson.
$myJson.profile.class would net you PrimalPlayerDataBP_C. That's how you access nested properties. As for the arrays, you can iterate through them with foreach, get specific values with where or select, depends on what you need actually.
# This one returns the version number
$version = ($myJson.profile.properties | Where {$_.name -eq "SavedPlayerDataVersion"}).value
# This one checks whether version is 8
$isVersion8 = $NULL -ne `
($myJson.profile.properties | Where {$_.name -eq "SavedPlayerDataVersion" -and $_.value -eq 8})
Be careful when accessing array items using their index, as you never can be sure that the item with a specific index is the one you're looking for.
As I'm writing this answer, #Theo beat me to it, so kudos to him for the one-liner.
EDIT:
Including a step-by-step example for clarity's sake. You can do the same with fewer lines.
# Get an array of properties
$properties = $myJson.profile.properties
# Select the property with the required name from the array
$myData = $properties | Where {$_.name -eq "MyData"}
# MyData is multivalued, so need to use 'Where' again
$playerDataId = $myData.value | Where {$_.name -eq "PlayerDataID"}
# Value you are looking for
$playerDataId.value
You can get the value you seek with a one-liner.
For demo I'm using a Here-String for your json data, but probably you would read that from file with $data = Get-Content -Path 'thefile.json' -Raw | ConvertFrom-Json
$data = #'
{
"profileVersion": 1,
"profile": {
"id": 0,
"class": "PrimalPlayerDataBP_C",
"names": ["PrimalPlayerDataBP_C_29", "ArkGameMode", "PersistentLevel", "Aberration_P", "/Game/Maps/Aberration/Aberration_P"],
"properties": [{
"name": "SavedPlayerDataVersion",
"type": "IntProperty",
"value": 8
}, {
"name": "HexagonCount",
"type": "IntProperty",
"value": 106860
}, {
"name": "MyPersistentBuffDatas",
"type": "ArrayProperty",
"arrayType": "ObjectProperty",
"value": [1, 2, 3, 4]
}],
"extra": null
}
}
'# | ConvertFrom-Json
Then, to get the value from property with name "SavedPlayerDataVersion" you simply do:
$value = ($data.profile.properties | Where-Object { $_.name -eq "SavedPlayerDataVersion" }).value
Variable $value will now contain 8
Simple example:
$json = '{ "one": 1, "two": 2 }'
$data = $json | ConvertFrom-Json | Select one
$myVal = $data.one
$myVal
The printed output will be 1
In your case:
$json = '{
"profileVersion": 1,
"profile": {
"id": 0,
"class": "PrimalPlayerDataBP_C",
"names": ["PrimalPlayerDataBP_C_29", "ArkGameMode", "PersistentLevel", "Aberration_P", "/Game/Maps/Aberration/Aberration_P"],
"properties": [{
"name": "SavedPlayerDataVersion",
"type": "IntProperty",
"value": 8
}, {
"name": "HexagonCount",
"type": "IntProperty",
"value": 106860
}, {
"name": "MyPersistentBuffDatas",
"type": "ArrayProperty",
"arrayType": "ObjectProperty",
"value": [1, 2, 3, 4]
}],
"extra": null
}}'
$data = $json | ConvertFrom-Json | Select -expand profile | Select -expand properties | Select name, type, value
$myVal = $data[0].value
$myVal

How to modify Json using Powershell

I have the following JSON held in a file "test.json":
{
"metadata": [
{
"src": [
{
"files": [
"src/**.csproj"
]
}
],
"dest": "api",
"disableGitFeatures": false,
"disableDefaultFilter": false
}
]
}
I'd like to modify the "src" element. Instead of:
"src": [
{
"files": [
"src/**.csproj"
]
}
],
It needs to be:
"src": [
{
"files": [
"*.csproj"
],
"cwd":".."
}
],
Where I modify the first element of "files" and add "cwd". This should be straight forward but I'm struggling to achieve this in powershell. Can anyone point me in the right direction of any examples of this?
Thanks for any pointers in advance.
You can do the following:
$JSONObject = Get-Content test.json -Raw | ConvertFrom-Json
$JSONObject.metadata.src.files = ,'*.csproj'
$JSONObject.metadata.src | Add-Member -Name 'cwd' -Value '..' -MemberType NoteProperty
$JSONObject | ConvertTo-Json -Depth 5 | Set-Content test.json
The tricky part is to make sure the .files value is an array of a single element. You can do this with the array subexpression operator #() or the unary operator ,.

How do I update JSON file using PowerShell

I have one json file mytest.json like below I want to update values using PowerShell script
update.json
{
"update": [
{
"Name": "test1",
"Version": "2.1"
},
{
"Name": "test2",
"Version": "2.1"
}
]
}
I want to write a PowerShell script where if Name=="test1" I want to update Version= "3"
How can i do it using parameters?
Here is a way :
$a = Get-Content 'D:\temp\mytest.json' -raw | ConvertFrom-Json
$a.update | % {if($_.name -eq 'test1'){$_.version=3.0}}
$a | ConvertTo-Json -depth 32| set-content 'D:\temp\mytestBis.json'
According to #FLGMwt and #mikemaccana I improve the ConvertTo-Json with -depth 32 because the default depth value is 2 and for object deeper than 2 you will receive class informations in spite of objects.
I have also faced the same kind of issue. I was looking to change the records of the below JSON file
{
"SQS_QUEUE_URL": "https://que-url.com/server1",
"SQS_EVENTS_QUEUE_URL": "https://events-server.com/server1/development_events",
"REGION": "region1",
"BUCKET": "test-bucket",
"AE_WORK_PATH": "C:\\workpath\\path1",
"ENV": "env"
}
Finally, I managed to find the easiest way to generate a JSON file from Powershell.
$json = Get-Content "c:\users\bharat.gadade\desktop\test.json" | ConvertFrom-Json
$json.SQS_QUEUE_URL = "https://que-url.com/server2"
$json.SQS_EVENTS_QUEUE_URL = "https://events-server.com/Server2/development_events"
$json.REGION = "region1 "
$json.BUCKET = "test-bucket"
$json.AE_WORK_PATH = "C:\workpath\path1"
$json.ENV = "env"
$json | ConvertTo-Json | Out-File "c:\users\bharat.gadade\desktop\test.json"

How to save a JSON object to a file using Powershell?

I have converted the following JSON file to powershell representation object.
{
"computer": [
{
"children": [
{
"children": [ {
"children": [ {
"path": "T:\Dropbox\kvaki.html",
"name": "kvaki",
"type": "url",
"url": "http://example.com"
} ],
"path": "T:\Dropbox\",
"name": "Njusha",
"type": "folder"
}, {
"path": "T:\Dropbox\Europa.html",
"name": "Europa",
"type": "url",
"url": "http://example.com"
}, {
"path": "T:\Dropbox\math.html",
"name": "math",
"type": "url",
"url": "http://example.com"
} ],
"path": "T:\Dropbox\",
"name": "Money",
"type": "folder"
}
],
"full_path_on_file_sys": "T:\Dropbox\"
}
]
}
After doing some computations with powershell representation I would like to save it to file as JSON.
But command $jsonRepresentation | ConvertTo-Json | Out-File "D:\dummy_path\file.json" saves it in this way
{
"computer": [
{
"children": " ",
"full_path_on_file_sys": "T:\Dropbox\"
}
]
}
Question: how to achieve correct saving of complex powershell JSON representation?
-depth argument for ConvertTo-Json solves the issue.
$jsonRepresentation | ConvertTo-Json -depth 100 | Out-File "D:\dummy_path\file.json"
Just pipe it to Set-Content, or Out-File:
Get-Process powershell |
ConvertTo-Json |
Set-Content json.txt
If you want to both view the output and save it to file, you can pipe the tee command.
Get-Process powershell | ConvertTo-Json | Tee-Object json.txt
$json.properties.metadata | ConvertTo-Json -Compress
if you are stuck with PowerShell Version 2, the JSON module of Joel Bennett from the 'PowerShell Code Repository' might help.
1) The below command can be used to convert a json to CSV
Example:
Get-Content package.json | Out-String | ConvertFrom-Json | Select parameter1, parameter2, parameter3 | ConvertTo-Csv -NoTypeInformation | Format-Table >> C:\JenkinsWorkspace\Result.csv
Get-Content: This is like "cat" command in linux which will get all data of file "package.json" and converts from Json (Using ConvertFrom-Json function) extracting the details of only required parameters and then converting them into CSV using "ConvertTo-Csv" function without any unwanted Type Headers and formatting them into Table.
2) The above result can also be formatted into proper csv to view it as Excel format without any duplicates and also having Text-To-Column conversion using below command:
Import-Csv "C:\Result.csv" -delimiter "," | Sort-Object _from -Unique | Export-csv "C:\FINAL_REPORT_$date.csv"