Powershell trouble getting value from key named count - json

I have a simple json that I am trying to get values from in Powershell
$webData = #'
{
"results": [
{
"facet": "266976",
"appid": "266976",
"count": 233206
},
{
"facet": "27096405",
"appid": "27096405",
"count": 85669
}
]
}
'#
$data1 = $webData | ConvertFrom-Json
Write-Output $data1.results.count
When I write output I get values count and not value itself like I do for appid and facet.
Desired result: 233206
Current result: 2
I cannot change json.
Is there a way for PS not to see it as a count operator?
Thank you

As mklement0 notes, in this case the array type's ICollection.Count property takes precedence over member access enumeration of the array-element property named Count.
A simple workaround is to use the intrinsic method .ForEach(string PropertyName):
$data1.results.ForEach('count')
As Santiago Squarzon notes, the type of ForEach() output is Collection`1. If you actually need an array, use the array sub-expression operator #() or use the workaround suggested by Santiago, using GetEnumerator().
$arrayOfCount = #($data1.results.ForEach('count'))
$arrayOfCount = $data1.results.GetEnumerator().Count
Output:
233206
85669
As Santiago Squarzon noted, if you actually want to get the value of count for the first object only, you can write:
$data1.results[0].Count
Output:
233206
Note that Write-Output is effectively redundant, because PowerShell implicitly outputs the "result" of any statement. So I've removed it in the samples above.

Related

JQ - Select JSON subarray by value then update by index

I'm trying to process some JSON output and modify a value but struggling to get anywhere.
I have no control over the source data, which looks like this:
[
[
"dave",
"likes",
"rabbits"
],
[
"brian",
"likes",
"fish"
]
]
In pseudo code, I need to:
Select the subarray with value "brian" at index 0
Change the value at index [2] in the selected array to "cats"
Return the complete modified array
I've managed to use map and select to get the subarray I want (jq -r -c 'map(select(.[]=="brian"))), but not build that into anything more useful...
Help much appreciated!
Update the required value by specifying the array indices and using the |= update select construct
map(select(.[0] == "brian")[2] |= "cats" )
This also populates [2] with "cats" even if previously there was no value at the specific index.
Of course it goes without saying, the indices could be dynamically arrived at as well
map(select(any(.[]; . == "brian"))[2] |= "cats")

Return objects in list that the first name starts with a certain value

I am trying to filter through this list of objects and only return the objects where the firstName starts with a specific value.
[
{"firstName":"Paul","lastName":"Collins"},
{"firstName":"Jerry","lastName":"Johnson"},
{"firstName":"Jody","lastName":"Johnson","occupation":"Occupado","company":"Companio"},
{"firstName":"Paul","lastName":"Johanson","occupation":"Developer","company":"Developer Co"}
]
The farthest I've gotten is this:
([].firstName | [?starts_with(#,'J') == `true`])
Which returns:
[
"Jerry",
"Jody"
]
However, I want to return whole objects that fit this condition, not just the firstName field. My desired output would be:
[
{"firstName":"Jerry","lastName":"Johnson"},
{"firstName":"Jody","lastName":"Johnson","occupation":"Occupado","company":"Companio"},
]
I couldn't find a way to pass an array of strings to starts_with. I could get the values from the return and interpolate them into multiple queries one query with a bunch of "|| firstName == name1 || firstName == name2". However I am wanting to try to do this in one query string.
Any ideas?
In JMESPath, if that's what you are looking for, the filter projection can be applied on any property of an array, by simply specifying the said properties in the brackets selecting the array itself.
So, rather than going [].firstName, the property comes inside the brackets, e.g. [?firstName == 'Jerry'], would give you the whole object of the person named Jerry.
Then you can apply this using start_with():
[?starts_with(firstName,'J')]
Which will yield the expected
[
{
"firstName": "Jerry",
"lastName": "Johnson"
},
{
"firstName": "Jody",
"lastName": "Johnson",
"occupation": "Occupado",
"company": "Companio"
}
]
Use select( ... ) to filter a stream. By extension, you can use map( select( ... ) ) to remove items from an array.
map( select( .firstName | startswith("J") ) )
Demo

JQ: Convert Dictionary with List as Values to flat CSV

Original Data
I have the following JSON:
{
"foo":[
"asd",
"fgh"
],
"bar":[
"abc",
"xyz",
"ert"
],
"baz":[
"something"
]
}
Now I want to transform it to a "flat" CSV, such that for every key in my object the list in the value is expanded to n rows with n being the number of entries in the respective list.
Expected Output
foo;asd
foo;fgh
bar;abc
bar;xyz
bar;ert
baz;something
Approaches
I guess I need to use to_entries and then for each .value repeat the same .key for the first column. The jq docs state that:
Thus as functions as something of a foreach loop.
So I tried combining
to_entriesto give the keys and values from my dictionary an accessible name
then build kind of a foreach loop around the .values
and pass the result to #csv
to_entries|map(.value) as $v|what goes here?|#csv
I prepared something that at least compiles here
Don't need to use _entries function, a simple key/value lookup and string interpolation should suffice
keys_unsorted[] as $k | "\($k);\( .[$k][])"
The construct .[$k][] is an expression that first expands the value associated with each key, i.e. .foo and then with object construction, produces multiple results for each key identified and stored in $k variable.

jsonPath - how to filter results by matching substring

I have a structure like this:
{"payload": {
"Item1": {
"property1": "Sunday",
"property2": "suffering_8890"
},
"Item2": {
"property1": "Monday",
"property2": "misery_0776"
},
"Item3": {
"property1": "Tuesday",
"property2": "pain_6756"
}
}
}
I need the property2 value that contains a certain sub-string (i.e- "misery"). Ultimately I just need the 4-digit code, but even getting the full value will work. I am able to get a list of all the property2 values by using:
$..property2
This returns:
Result[0] = suffering_8890
Result[1] = misery_0776
Result[2] = pain_6756
How do I filter it so that it only gives me the result containing the substring "misery"?
With regards to full value you can use a Filter Operator like:
$..[?(#.property2 =~ /misery.*?/i)].property2
Demo:
You can extract the 4-digit value out of the variable using Regular Expression Extractor
If you want to do this in one shot:
Add JSR223 PostProcessor as a child of the request which returns above JSON
Put the following code into "Script" area
vars.put('misery', ((com.jayway.jsonpath.JsonPath.read(prev.getResponseDataAsString(), '$..[?(#.property2 =~ /misery.*?/i)].property2').get(0) =~ ('(\\d+)'))[0][1]))
Refer the extracted value as ${misery} where required
More information: Apache Groovy - Why and How You Should Use It
You can use a regular expression extractor as well for the mentioned scenario to fetch the four-digit as below
property2": "misery_(.*)"
This will help you to save the four-digit code in JMeter variables right away. If you insist you to find out the required value from JSON using jsonpath, you can use JSON filter as below :-
$..[?(#.property2.indexOf('misery')>=0)]..property2

Having separate arrays, how to extract value based on the column name?

I am trying to extract data from some JSON with JQ - I have already got it down to the last level of data that I need to extract from, but I am completely stumped as to how to proceed with how this part of the data is formatted.
An example would be:
{
"values": [
[
1483633677,
42
]
],
"columns": [
"time",
"count_value"
],
"name": "response_time_error"
}
I would want to extract just the value for a certain column (e.g. count_value) and I can extract it by using [-1] in this specific case, but I want to select the column by its name in case they change in the future.
If you're only extracting a single value and the arrays will always correspond with eachother, you could find the index in the columns array then use that index into the values array.
It seems like values is an array of rows with those values. Assuming you want to output the values of all rows with the selected column:
$ jq --arg col 'count_value' '.values[][.columns | index($col)]' input.json
If the specified column name does not exist in .columns, then Jeff's filter will fail with a rather obscure error message. It might therefore be preferable to check whether the column name is found. Here is an illustration of how to do so:
jq --arg col count_value '
(.columns | index($col)) as $ix
| if $ix then .values[][$ix] else empty end' input.json
If you want an informative error message to be printed, then replace empty with something like:
error("specified column name, \($col), not found")