Get the node value from json in powershell - json

I have json body in powershell variable and want to get value from it.
Json Body :
"value": [
{
"id": 1,
"scope": "3e93f9e6-f427-48e1-b37b-994d196e1121",
"name": "Default",
"isHosted": false,
"poolType": "automation",
"size": 3
},
{
"id": 2,
"scope": "3e93f9e6-f427-48e1-b37b-994d196e1121",
"name": "Hosted",
"isHosted": true,
"poolType": "automation",
"size": 10
},
{
"id": 4,
"scope": "3e93f9e6-f427-48e1-b37b-994d196e1121",
"name": "Hosted VS2017",
"isHosted": true,
"poolType": "automation",
"size": 10
}]
I want to get the id value where name=Hosted VS2017 i.e 4
powershell :
Write-Host "json body:" $projects
$id = $projects.value | where { $_.name -eq "Hosted VS2017" }
Write-Host "id :" $id

You need to convert your JSON into a powershell object before you can work with it:
$projects = $projects | ConvertFrom-Json
Then you can access its members:
#requires -Version 3
$projects.value | ? name -eq 'Hosted VS2017'

Related

Parse json values into a single row

{
"value": [{
"ExternalKey": "12345",
"PortfolioId": "ABC",
"InceptionDate": null,
"TerminationDate": null,
"Version": 2,
"SourceRef": "ABC",
"MasterSeries": [{
"Points": [{
"Date": "1900-01-01T00:00:00+00:00",
"Name": "XYZ Name",
"Type": "IP",
"Status": "Active",
"Version": 1
}],
"ExternalKey": "12345",
"Version": 1,
"IsDeleted": false,
"SourceRef": "ABC"
}]
}]
}
I tried to loop through each level and manually selecting the keys
ForEach($d in $json.value) { $row=$d.column1+","+ $d.column2 ..
$rootProps = $d| Get-Member | Where-Object { $_.MemberType -match "Property"}
$rootProps | ForEach-Object {
if($_.Name -eq "MasterSeries") {
$d | select -Expand MasterSeries | select-object * -ExcludeProperty Points | ForEach { $row = $_.column1 + "," $_.column2 ..
}
}
and so on..... but when I export it to Out-File "Export.csv" and try importing it gives me a UTF error. Is there a better way to achieve?
If this helps any, here's the typical way to loop through json properties in powershell 5 using the hidden psobject.properties. You might search for "flatten json".
$a = get-content file.json | convertfrom-json
$a.value[0].psobject.properties | select name,value
Name Value
---- -----
ExternalKey 12345
PortfolioId ABC
InceptionDate
TerminationDate
Version 2
SourceRef ABC
MasterSeries
For this you will need to create a recursive function.
To make things easier, I recommend you to use the ConvertFrom-Json -AsHashTable parameter which will return [HashTable] objects rather than [PSCustomObject] Objects
Function Get-Values($Object) {
if ($Object -is [String]) { $Object } # A string is also Enumerable
elseif ($Object -is [Collections.IDictionary]) { $Object.get_Values() | ForEach-Object { Get-Values $_ } }
elseif ($Object -is [Collections.IEnumerable]) { $Object.GetEnumerator() | ForEach-Object { Get-Values $_ } }
else { $Object }
}
$Object = ConvertFrom-Json -AsHashTable '{
"value": [
{
"ExternalKey": "12345",
"PortfolioId": "ABC",
"InceptionDate": null,
"TerminationDate": null,
"Version": 2,
"SourceRef": "ABC",
"MasterSeries": [
{
"Points": [
{
"Date": "1900-01-01T01:00:00+01:00",
"Name": "XYZ Name",
"Type": "IP",
"Status": "Active",
"Version": 1
}
],
"ExternalKey": "12345",
"Version": 1,
"IsDeleted": false,
"SourceRef": "ABC"
}
]
}
]
}'
Get-Values $Object
12345
False
1
IP
Monday, January 1, 1900 1:00:00 AM
XYZ Name
Active
ABC
1
12345
2
ABC
ABC

JSON file specific keywork via powershell

I want to get lines which are serviceArea equal Skype like below.
{
"id": 127,
"serviceArea": "Skype",
"serviceAreaDisplayName": "Skype for Business Online and Microsoft Teams",
"urls": [
"*.skype.com"
],
"tcpPorts": "80,443",
"expressRoute": false,
"category": "Default",
"required": true
},
{
"id": 128,
"serviceArea": "Common",
"serviceAreaDisplayName": "Microsoft 365 Common and Office Online",
"urls": [
"*.config.office.net",
"*.manage.microsoft.com"
],
"tcpPorts": "443",
"expressRoute": false,
"category": "Default",
"required": true
},
{
"id": 130,
"serviceArea": "Common",
"serviceAreaDisplayName": "Microsoft 365 Common and Office Online",
"urls": [
"lpcres.delve.office.com"
],
"tcpPorts": "443",
"expressRoute": false,
"category": "Default",
"required": true
},
{
"id": 146,
"serviceArea": "Skype",
"serviceAreaDisplayName": "Skype for Business Online and Microsoft Teams",
"urls": [
"statics.teams.microsoft.com"
],
"tcpPorts": "443",
"expressRoute": false,
"category": "Default",
"required": true
}
My desired output :
*.skype.com
statics.teams.microsoft.com
Assuming your JSON is wrapped in an array (as mentioned in comments above), you could do something like this to filter the data.
param(
$jsonFile = "$PSScriptRoot\data.json",
$likeFilter = "*Skype*"
)
$convertedObjects = Get-Content -Path $jsonFile | ConvertFrom-Json
$result = $convertedObjects | Where-Object { $_.serviceArea -like $likeFilter }
$result
Your JSON is invalid due to is has no root element. As I see, it is array (list)
$text = #'
[
<your text here>
]
'#
After that, you can select urls
$result = $text |
ConvertFrom-Json |
Where-Object { $_.serviceArea -eq 'Skype' } |
ForEach-Object { return $_.urls }

Create a json document based on existing document with powershell 5.1

I'm trying to build a json document which takes it's structure, column names and some values from an already existing base json document, and sets other values to variables assigned via powershell 5.1 in a foreach-object loop.
I tried editing a copy of the base json and creating a new one entirely and I can get close to what I want but not exactly.
A cut down example json document is:
[
{
"name": "Application1",
"tags": ["monitor"],
"description": "Get information about application 1.",
"query":
[
{
"target": {
"version": ["v1","v2","v3","v4","v5"],
"platform": ["Windows","Linux"]
},
"implementation": {
"action": "do something"
}
}
]
},
{
"name": "Application2",
"tags": ["monitor"],
"description": "Get information about application 2",
"query":
[
{
"target": {
"version": ["v1","v2","v3"],
"platform": ["Windows"]
},
"implementation": {
"action": "do something for v1, v2 and v3"
}
},
{
"target": {
"version": ["v4","v5"],
"platform": ["Windows"]
},
"implementation": {
"action": "do something for v4 and v5"
}
}
]
}
]
My script currently looks like:
$BaseJson = (Get-Content "$SourcePath\probes.json" | ConvertFrom-Json)
$ClientConfig = #"
{
"targetHost": "$DigitalSymphonyHost",
"targetPort": "$DigitalSymphonyPort",
"source": "$TargetSqlInstance",
"sensor": {}
}
"#
$ClientJson = ConvertFrom-Json -InputObject $ClientConfig
$BaseJson | Where-Object {$_.tags -contains "monitor"} | ForEach-Object {
# For each sensor in the base-sensors json document
$SensorName = $_.name
$Severity = 2
$Version = $_.query.target.version
$Platform = $_.query.target.platform
$Query = $_.query.implementation.action
$Sensor =#"
{
"severity": "$Severity",
"sensorId": "$SensorId",
"type": "$Type",
"target": {
"version": "$Version",
"platform": "$Platform",
"engineEdition": "$Edition"
},
"implementation": {
"query": "$Query"
}
}
"#
$ClientJson.sensor | Add-Member -Name $SensorName -Value (ConvertFrom-Json $Sensor) -MemberType NoteProperty
}
$ClientJson | ConvertTo-Json | Out-File "$DestinationPath\client-sensors.json"
My desired result is to add the $SensorId as per:
[
{
"targetHost": "servername",
"targetPort": "port",
"source": "servername",
"sensor": [{
"name": "Application1",
"sensorId": "<value_from_$SensorId>",
"tags": [],
"description": "Get information about application 1.",
"query":
[
{
"target": {
"version": ["v1","v2","v3","v4","v5"],
"platform": ["Windows","Linux"]
},
"implementation": {
"action": "do something"
}
}
]
},
{
"name": "Application2",
"sensorId": "<value_from_$SensorId>",
"tags": [],
"description": "Get information about application 2",
"query":
[
{
"target": {
"version": ["v1","v2","v3"],
"platform": ["Windows"]
},
"implementation": {
"action": "do something for v1, v2 and v3"
}
},
{
"target": {
"version": ["v4","v5"],
"platform": ["Windows"]
},
"implementation": {
"action": "do something for v4 and v5"
}
}
]
}]
}
]
My current result is
{
"targetHost": "servername",
"targetPort": "port",
"source": "server",
"sensor": {
"applicationname1": {
"tags": ["monitor],
"description": "Get information about application 2",
"sensorId": "420",
"target": "#{version=v1,v2,v3,v4,v5; platform=Windows Windows;}",
"action": "do something for v4 and v5"
}
}
}
I'm not sure where you're getting sensorID, but I'd do this more like the below:
param(
$SourcePath = $PSScriptRoot,
$DestinationPath = $PSScriptRoot,
$DigitalSymphonyHost = 'SomeHost',
$DigitalSymphonyPort = '8765',
$TargetSqlInstance
)
$BaseObj = (Get-Content "$SourcePath\probes.json" | ConvertFrom-Json)
$Client = [PSCustomObject] #{
targetHost = $DigitalSymphonyHost
targetPort = $DigitalSymphonyPort
source = $TargetSqlInstance
sensor = #()
}
$BaseObj | Where-Object {$_.tags -contains "monitor"} | ForEach-Object {
$sensor = $_
# TODO: How are you getting sensorId?
$sensor | Add-Member -Name 'sensorId' -Value 777 -MemberType NoteProperty
$Client.sensor += $sensor
}
ConvertTo-Json #($Client) -Depth 10 | Out-File "$DestinationPath\client-sensors.json" -Force
That will get you the JSON you're looking for.

Need to search a text file for a string and capture a second string located after the first

I'm working with an API call and I need to parse the JSON returned by the API in PowerShell. I'm searching for a particular name and then I need to capture a another item that follows it.
$json = #"
{
"Test": [
{
"association": "(None)",
"description": "",
"displayName": "BusIntel48.png",
"galleryImage": "[PlugIn]Images;Trebuchet.PlugIn.Images.Images.Common.BusIntelligence.BusIntel48.png",
"id": "944f73cc5c1a812eaa2ade43bd9ca0c9a40f963c56",
"links": [],
"localizedScopeName": "Built in",
"name": "BusIntel48.png",
"parentFolder": "ImagesCommonBusIntelligence",
"parentIsScopeFolder": false,
"scope": "FromResource",
"scopeOwner": "",
"standInKey": "DefType:ImageDef#Scope:FromResource#Id:944f73cc5c1a812eaa2ade43bd9ca0c9a40f963c56"
},
{
"association": "(None)",
"description": "",
"displayName": "BusProcActOnEvent16.png",
"galleryImage": "[PlugIn]Images;Trebuchet.PlugIn.Images.Images.Common.BusIntelligence.BusProcActOnEvent16.png",
"id": "944f73cc5cb33339be6db84987baef3f7190c931cf",
"links": [],
"localizedScopeName": "Built in",
"name": "BusProcActOnEvent16.png",
"parentFolder": "ImagesCommonBusIntelligence",
"parentIsScopeFolder": false,
"scope": "FromResource",
"scopeOwner": "",
"standInKey": "DefType:ImageDef#Scope:FromResource#Id:944f73cc5cb33339be6db84987baef3f7190c931cf"
}
]
}
"#
$x = $json | ConvertFrom-Json
$name = $x.Test | where { $_.name -eq "BusIntel48.png" }
I need to search for the name of the image file (ex. "name": "BusIntel48.png") and then capture the string after "standInKey: (ex. DefType:ImageDef#Scope:FromResource#Id:944f73cc5c1a812eaa2ade43bd9ca0c9a40f963c56).
Just need a change in last line.
You can also select one property by using :
$name = $x.Test | where { $_.name -eq "BusIntel48.png" } | Select-Object -Property "standInKey"

Select a node from a JSON file that matches a property value

I am having a json object stored in a variable. From the json object, I want to fetch the node which matches a value. For example - an item having machineId 12.
My json looks like
{
"items": [
{
"id": "asdasd",
"machineId": "12",
"placementGroup": "",
"region": "158",
"staticIp": "",
"staticIpAction": "",
"subnetIDs": [
]
},
{
"id": "asdasd",
"machineId": "43",
"placementGroup": "",
"region": "158",
"staticIp": "",
"staticIpAction": "",
"subnetIDs": [
]
}
]
}
Load the json using the Get-Content cmdlet and convert it to json using the ConvertFrom-Json cmdlet. Select the items node and filter it by the desired machineId using the Where-Object cmdlet:
Get-Content 'yourPathToYour.json' |
ConvertFrom-Json |
Select-Object -ExpandProperty items |
Where-Object machineId -eq 12
Output:
id : asdasd
machineId : 12
placementGroup :
region : 158
staticIp :
staticIpAction :
subnetIDs : {}