I've got this json file:
[
{
"group": [313, 312, 313, 311],
"group_name": ["example", "example", "example1"],
"status": ["not_available_time", "no_time"]
}
]
And in Powershell I want the output to be:
313, example, not_available_time
So I always need just the first value.
I've tried this:
$responseJson = ConvertFrom-Json $response.Content
$group = $responseJson.group[0]
$name = $responseJson.group_name[0]
$status = $responseJson.status[0]
That works. But only if there is always more than one value.
For example: if "group_name" in the JSON file would only hold the value "example" (and not ["example", "example", "example1"]) => the output would only be "e" instead of "example". It takes not the first value, but only the first letter if there is only one value.
How can I select the first value?
BR and thanks!
There are 2 safe methods to ensure you're always selecting the first Value, be it an array, a scalar or null:
You can use the array subexpression operator #(), which will ensure that even if the value is $null or [System.Management.Automation.Internal.AutomationNull]::Value the result will always be an array (object[]):
#([System.Management.Automation.Internal.AutomationNull]::Value).GetType().Name # => Object[]
#($null).GetType().Name # => Object[]
As an alternative, Select-Object with the -First 1 argument, the difference is the returned object's Type remains the same:
(1 | Select-Object -First 1).GetType().Name # => Int32
('a', 'b' | Select-Object -First 1).GetType().Name # => String
$null -eq ($null, $null | Select-Object -First 1) # => True
Both alternatives are valid and depends on your use case which one fits your need better:
$json = #'
[
{
"group": [313, 312, 313, 311],
"group_name": "single_element",
"status": null
}
]
'# | ConvertFrom-Json
$json.PSObject.Properties | ForEach-Object {
$arr = #($_.Value)[0]
$slo = $_.Value | Select-Object -First 1
[pscustomobject]#{
'ArraySubExpression' = "[ {0}: $arr ]" -f $_.Name
'Select-Object' = "[ {0}: $slo ]" -f $_.Name
}
}
ArraySubExpression Select-Object
------------------ -------------
[ group: 313 ] [ group: 313 ]
[ group_name: single_element ] [ group_name: single_element ]
[ status: ] [ status: ]
Related
I want to get specific value once key is matched from JSON array object
Input:
[
{
"Id": "19A7A3C4",
"displayName": "somename",
"tags": [
{
"context": "CONTEXTLESS",
"key": "apple",
"value": "10"
},
{
"context": "CONTEXTLESS",
"key": "orange",
"value": "20"
},
{
"context": "CONTEXTLESS",
"key": "grapes",
"value": "30"
}
]
},
{
"Id": "111111",
"displayName": "somename",
"tags": [
{
"context": "CONTEXTLESS",
"key": "cat",
"value": "10"
},
{
"context": "CONTEXTLESS",
"key": "cat",
"value": "20"
}
]
}
]
I want to get the value of tag where key matches to cat and value matches to 10, I am using below query but getting whole object
$content = Get-Content -Raw -Path "data.json" | ConvertFrom-Json
$content | Where-Object{ $_.tags.key -eq "cat" -and $_.tags.value -eq "10"}
Desired Output: 10
Mathias's answer already shows a clean way to solve the problem.
A similar approach is using the intrinsic method .Where{}:
$tagValues = $content.tags.Where{ $_.key -eq "cat" -and $_.value -eq "10" }.value
$content.tags employs member enumeration to collect all tags properties into an array. .Where{} filters array elements similar to Where-Object. Lastly .value uses member enumeration again to collect the filtered tag values into an array.
Intrinsic methods like .Where{} are supposed to be faster than pipeline commands because they don't involve the overhead of the pipeline machinery.
If you want to keep your original query, you have to deal with nested properties.
Use grouping operator () and dot notation to extract a given property:
$tagValues = ($content | Where-Object{ $_.tags.key -eq "cat" -and $_.tags.value -eq "10"}).tags.value
An alternative is Select-Object with parameter -ExpandProperty (alias -Expand), but it doesn't work as straightforward for nested properties (yet):
$tagValues = $content | Where-Object{ $_.tags.key -eq "cat" -and $_.tags.value -eq "10"} |
Select-Object -Expand tags | Select-Object -Expand value
A more straightforward alternative is ForEach-Object:
$tagValues = $content | Where-Object{ $_.tags.key -eq "cat" -and $_.tags.value -eq "10"} |
ForEach-Object { $_.tags.value }
Enumerate all tags, then use ForEach-Object to grab just the value property of any match:
$content.tags | Where-Object { $_.key -eq "cat" -and $_.value -eq "10"} |ForEach-Object -MemberName value
Given the following JSON
[
{
"key": "James",
"things": [
{
"id": 123,
"name": "PRD"
},
{
"id": 124,
"name": "PRE"
}
]
},
{
"key": "Susan",
"things": [
{
"id": 125,
"name": "PRF"
},
{
"id": 126,
"name": "PRG"
}
]
}
]
Which, I've easily converted into a Powershell object:
$json = '[{"key":"James", "things":[{"id":123,"name":"PRD"},{"id":124,"name":"PRE"}]},{"key":"Susan", "things":[{"id":125,"name":"PRF"},{"id":126,"name":"PRG"}]}]'
$obj = $json | ConvertFrom-Json
How do I flatten the sub-array things and include the key from the parent object, so that my result set is
key id name
--- -- ----
James 123 PRD
James 124 PRE
Susan 125 PRF
Susan 126 PRG
I've used the following to flatten the sub-array:
$obj | % { $_.things}
Which returns me
id name
-- ----
123 PRD
124 PRE
125 PRF
126 PRG
But, I can't quite figure out what to do next.
Any help would be much appreciated.
You loop into each key, then loop into each things, since you want 1 result per thing, and build a PSObject using the current key, id and name.
Here you go.
# initial code sample
$json = '[{"key":"James", "things":[{"id":123,"name":"PRD"},{"id":124,"name":"PRE"}]},{"key":"Susan", "things":[{"id":125,"name":"PRF"},{"id":126,"name":"PRG"}]}]'
$obj = $json | ConvertFrom-Json
# Loop needed to flatten the object.
foreach ($i in $obj) {
foreach ($t in $i.things) {
[PSCustomObject]#{
key = $i.key
id = $t.id
name = $t.name
}
}
}
Output
key id name
--- -- ----
James 123 PRD
James 124 PRE
Susan 125 PRF
Susan 126 PRG
you can use built-in flattening with select as follows:
($json | ConvertFrom-Json) | Select-Object key -ExpandProperty things
I am trying to get the key value from object inside JSON array, please also suggest if I need to change my RuleId key structure, below is the output I want
rule = 1300
rulevalue = false
rule = 1304
rulevalue = true
JSON file
{
"Rule": [{
"MPName": "ManagementPackProject",
"Request": "Apply",
"Category": "Rule",
"RuleId": {
"1300": "false",
"1304": "true"
}
}]
}
PowerShell
$Content = Get-Content -Raw -Path "C:\temp\Rule.json" | ConvertFrom-Json -ErrorAction Stop
$Content = $Content.Rule | Where-Object { $_.Request -eq "Apply" }
foreach($item in $Content.RuleId)
{
rule = $item.key
rulevalue = $item.value
process...
}
Are you after something like this?
$JSON = #'
{
"Rule": [{
"MPName": "ManagementPackProject",
"Request": "Apply",
"Category": "Rule",
"RuleId": {
"1300": "false",
"1304": "true"
}
}]
}
'#
$Content = $JSON | ConvertFrom-Json
$Content = $Content.Rule | Where-Object Request -eq 'Apply'
$Output = foreach( $Rule in $Content.RuleId.psobject.Properties ) {
[PSCustomObject]#{
Rule = $Rule.Name
RuleValue = $Rule.Value
}
}
$Output | Format-List
Output:
Rule : 1300
RuleValue : false
Rule : 1304
RuleValue : true
I have a simple ARM template that outputs an array of elements. I am trying to retrieve said array of elements in powershell, but nothing seems to help. It seems like the deployment result does contain the values of the array, but as soon as I try to navigate to it they become empty strings.
Ideally I want to retrieve the array output from the ARM template into a powershell variable.
ARM template:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
},
"variables": {
"test": [
"value1",
"value2"
]
},
"resources": [
],
"outputs": {
"result": {
"type": "array",
"value": "[variables('test')]"
}
}
}
Everything I have tried:
Powershell code:
$name = ((Get-Date).ToUniversalTime()).ToString('MMdd-HHmmss')
$deploymentResult = New-AzureRmResourceGroupDeployment `
-Name $name `
-ResourceGroupName test4 `
-TemplateFile 'test2.json' `
-Force -Verbose `
-ErrorVariable ErrorMessages
if ($ErrorMessages) {
Write-Output '', 'Template deployment returned the following errors:', #(#($ErrorMessages) | ForEach-Object { $_.Exception.Message.TrimEnd("`r`n") })
}
Write-Output $deploymentResult
Write-Host ($deploymentResult.outputs | Format-Table | Out-String)
Write-Host "Outputs:" $deploymentResult.outputs
Write-Host "Outputs.value:" $deploymentResult.outputs.value
Write-Host "Outputs.values:" $deploymentResult.outputs.values
Write-Host "Outputs[0]:" $deploymentResult.outputs[0]
Write-Host "Outputs[1]:" $deploymentResult.outputs[1]
Write-Host "Outputs[0].value:" $deploymentResult.outputs[0].value
Write-Host "Outputs[1].value:" $deploymentResult.outputs[1].value
Write-Host "Outputs.result:" $deploymentResult.outputs.result
Write-Host "Outputs.result.value:" $deploymentResult.outputs.result.value
Write-Host "Outputs.result.values:" $deploymentResult.outputs.result.values
Write-Host "Outputs.result[0]:" $deploymentResult.outputs.result[0]
Write-Host "Outputs.result[1]:" $deploymentResult.outputs.result[1]
Write-Host "Outputs.result[0].value:" $deploymentResult.outputs.result[0].value
Write-Host "Outputs.result[1].value:" $deploymentResult.outputs.result[1].value
Write-Host "Outputs.result[0][0]:" $deploymentResult.outputs.result[0][0]
Write-Host "Outputs.result.value1:" $deploymentResult.outputs.result.value1
Write-Host "Outputs.result[0].value1:" $deploymentResult.outputs.result[0].value1
Write-Host
Write-Host "Outputs.values:" $deploymentResult.outputs.values
Write-Host "Outputs.result.Count:" $deploymentResult.outputs.result.Count
Write-Host "Outputs.result:" $deploymentResult.outputs.result
Write-Host "Outputs.result[0]:" $deploymentResult.outputs.result[0]
Write-Host "Outputs['result']:" $deploymentResult.outputs['result']
Write-Host
Write-Host "Deployment properties:"
($deploymentResult) | Select-Object -Property *
Write-Host "Outputs properties:"
($deploymentResult.outputs) | Select-Object -Property *
Write-Host "Result properties:"
($deploymentResult.outputs.result) | Select-Object -Property *
Write-Host "['Result'] properties:"
$deploymentResult.outputs['result'] | Select-Object -Property *
Write-Host "[array]['Result'] properties:"
[array]$deploymentResult.outputs['result'] | Select-Object -Property *
Write-Host "Outputs.values properties:"
($deploymentResult.outputs.values) | Select-Object -Property *
Write-Host
ForEach ($res in $deploymentResult.outputs['result']){
Write-Host "Result element:" $res
}
Write-Host
ForEach ($res in $deploymentResult.outputs.values){
Write-Host "Values element:" $res
}
Write-Host
Write-Host "JSON:"
Write-Host "Deployment ConvertTo-Json:"
$json = ($deploymentResult) | ConvertTo-Json
Write-Host $json
Write-Host "Outputs ConvertTo-Json:"
$json = ($deploymentResult.outputs) | ConvertTo-Json
Write-Host $json
Write-Host "Result.Value ConvertTo-Json:"
$json = ($deploymentResult.outputs.result.value) | ConvertTo-Json
Write-Host $json
Powershell output:
VERBOSE: Performing the operation "Creating Deployment" on target "test4".
VERBOSE: 11:00:26 - Template is valid.
VERBOSE: 11:00:26 - Create template deployment '0521-100025'
VERBOSE: 11:00:26 - Checking deployment status in 5 seconds
DeploymentName : 0521-100025
ResourceGroupName : test4
ProvisioningState : Succeeded
Timestamp : 21/05/2020 10:00:26
Mode : Incremental
TemplateLink :
Parameters :
Outputs :
Name Type Value
=============== ========================= ==========
result Array [
"value1",
"value2"
]
DeploymentDebugLogLevel :
Key Value
--- -----
result Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.DeploymentVariable
Outputs: [result, Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.DeploymentVariable]
Outputs.value:
Outputs.values: Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.DeploymentVariable
Outputs[0]:
Outputs[1]:
Outputs[0].value:
Outputs[1].value:
Outputs.result: Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.DeploymentVariable
Outputs.result.value:
Outputs.result.values:
Outputs.result[0]: Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.DeploymentVariable
Outputs.result[1]:
Outputs.result[0].value:
Outputs.result[1].value:
Outputs.result[0][0]: Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.DeploymentVariable
Outputs.result.value1:
Outputs.result[0].value1:
Outputs.values: Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.DeploymentVariable
Outputs.result.Count: 1
Outputs.result: Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.DeploymentVariable
Outputs.result[0]: Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.DeploymentVariable
Outputs['result']: Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.DeploymentVariable
Deployment properties:
ResourceGroupName : test4
OnErrorDeployment :
DeploymentName : 0521-100025
CorrelationId : 10be00bb-fada-4b54-8749-87460672e9ec
ProvisioningState : Succeeded
Timestamp : 21/05/2020 10:00:26
Mode : Incremental
TemplateLink :
TemplateLinkString :
DeploymentDebugLogLevel :
Parameters : {}
ParametersString :
Outputs : {[result, Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.DeploymentVariable]}
OutputsString :
Name Type Value
=============== ========================= ==========
result Array [
"value1",
"value2"
]
Outputs properties:
Comparer : System.Collections.Generic.GenericEqualityComparer`1[System.String]
Count : 1
Keys : {result}
Values : {Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.DeploymentVariable}
IsReadOnly : False
IsFixedSize : False
SyncRoot : System.Object
IsSynchronized : False
Result properties:
Type : Array
Value : {, }
['Result'] properties:
Type : Array
Value : {, }
[array]['Result'] properties:
Type : Array
Value : {, }
Outputs.values properties:
Type : Array
Value : {, }
Result element: Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.DeploymentVariable
Values element: Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.DeploymentVariable
JSON:
Deployment ConvertTo-Json:
{
"ResourceGroupName": "test4",
"OnErrorDeployment": null,
"DeploymentName": "0521-100025",
"CorrelationId": "10be00bb-fada-4b54-8749-87460672e9ec",
"ProvisioningState": "Succeeded",
"Timestamp": "\/Date(1590055226689)\/",
"Mode": 0,
"TemplateLink": null,
"TemplateLinkString": null,
"DeploymentDebugLogLevel": null,
"Parameters": {
},
"ParametersString": "",
"Outputs": {
"result": {
"Type": "Array",
"Value": "value1 value2"
}
},
"OutputsString": "\r\nName Type Value \r\n=============== ========================= ==========\r\nresult Array [\r\n \"value1\",\r\n \"value2\"\r\n]\r\n"
}
Outputs ConvertTo-Json:
{
"result": {
"Type": "Array",
"Value": [
"",
""
]
}
}
Result.Value ConvertTo-Json:
[
[
],
[
]
]
The array output is in fact a JArray. Access the result like this: $deploymentResult.outputs.result.value[0].value and $deploymentResult.outputs.result.value[1].value.
More info: PowerShell -- Accessing a JArray inside a JObject
Below is the JSON file which i am referring..
{
"#odata.context": "https://ac.com/odata/$metadata#ModelVariableDataTypes(Id,ModelVariable,DoubleValues,ModelVariable(Id,Name,UnitOfMeasure,UnitOfMeasure(Name,Abbreviation)),DoubleValues(Id,Value,Timestamp,DataQuality,DataQuality(Id,Name)))",
"#odata.count": 1,
"value": [
{
"Id": 1928155,
"ModelVariable": {
"Id": 1929663,
"Name": "AccCore_CPULoadProcess",
"UnitOfMeasure": {
"Name": "%",
"Abbreviation": "%"
}
},
"DoubleValues": [
{
"Id": 75865549,
"Value": 0.0,
"Timestamp": "2018-09-25T03:35:00Z",
"DataQuality": {
"Id": 1,
"Name": "Good"
}
},
{
"Id": 75865729,
"Value": 0.0,
"Timestamp": "2018-09-25T03:40:00Z",
"DataQuality": {
"Id": 1,
"Name": "Good"
}
},
{
"Id": 75865873,
"Value": 0.0,
"Timestamp": "2018-09-25T03:45:00Z",
"DataQuality": {
"Id": 1,
"Name": "Good"
}
}
]
}
]
}
I want to extract the data present in JSON file from a odata url but i am unable to extract the content using a loop as in the JSON file the odata count is mentioned as 1(#odata.count": 1) so when i am trying to catch the entire data using a loop it is not working.
I want to extract the data present in the array field of doublevalues and wanted to show the output of the top three values of CPU process.
I am trying with the below code to extract the JSON data.
$path= "C:\Users\s.papolu\Desktop\mem.json"
$data = Get-Content -Path 'C:\Users\S.Papolu\Desktop\mem.json' | ConvertFrom-Json
$maxCount = $data.'#odata.count'
$maxCount
#"
for ($i = 0; $i -lt $maxCount; $i++)
{
$Name = $("{0:N1}" -f $data.value.ModelVariable.Name)
$cpu = $("{$i`:N2}" -f $data.value.DoubleValues.Value)
}
write-host $Name,$cpu
I'm not quite sure what you're asking here. For one thing, you've got an extraneous at-sign and double-quote in there.
MaxCount is just 1 here, so the loop only runs once. For each item, though, are you trying to store the results in some structure and then show it? Which of the DoubleValues do you want? The top three?
Is this closer to what you want?
$data = Get-Content -Path $path | ConvertFrom-Json
$maxCount = $data.'#odata.count'
$maxCount
$results = #()
for ($i = 0; $i -lt $maxCount; $i++)
{
# get the top three doubles values
$Doubles = #($data.value[$i].DoubleValues | sort -Property Value -Descending | select -first 3)
$results += [PsCustomObject]#{
Name = $data.value[$i].ModelVariable[0].Name;
Cpu = $Doubles;
}
}
$results | ft