JSONPath expression to look inside different keys - json

I have a JSON returned by a RESTful API:
{
"0": {
"id": "1484763",
"name": "Name",
"values": {
"0": {
"value": "Peter"
}
}
},
"1": {
"id": "2584763",
"name": "phone",
"values": {
"0": {
"value": "45456456"
}
}
}
}
How do I write a JSONPath that extracts a phone number value? (so in this case, "45456456"). What makes the problem harder, phone number object is not always inside "1" key.

Try this JsonPath which results in phone number 45456456
$..[?(#.name = 'phone')].values.0.value
Basically, you have to apply a filter ?() where name == 'phone' and then use normal json path.
Try the expression in this link
JsonPath expression syntax can be found here.

Related

Azure CI/CD Json transformation on array

When I'm creating a Task for an Azure DevOps release, can I transform the value of an object in an array, based on the "key" of the object?
As an example, I'm copying the example Json file from this article, which is this.
{
"Data": {
"DefaultConnection": {
"ConnectionString": "Data Source=(LocalDb)\\MSDB;AttachDbFilename=aspcore-local.mdf;"
},
"DebugMode": "enabled",
"DBAccess": {
"Administrators": ["Admin-1", "Admin-2"],
"Users": ["Vendor-1", "vendor-3"]
},
"FeatureFlags": {
"Preview": [
{
"newUI": "AllAccounts"
},
{
"NewWelcomeMessage": "Newusers"
}
]
}
}
}
What I have is something more like this, look at the "FeatureFlags" array. My array contains a list of "key"/"value" objects similar to this. I need to be able to transform the object in the array that matches a key, and have the transform process replace the "value" property value.
{
"Data": {
"DefaultConnection": {
"ConnectionString": "Data Source=(LocalDb)\\MSDB;AttachDbFilename=aspcore-local.mdf;"
},
"DebugMode": "enabled",
"DBAccess": {
"Administrators": ["Admin-1", "Admin-2"],
"Users": ["Vendor-1", "vendor-3"]
},
"FeatureFlags": {
"Preview": [
{
"key": "newUI",
"value": "AllAccounts"
},
{
"key": "NewWelcomeMessage",
"value": "Newusers"
}
]
}
}
}
For example, I want to change the value of "Newusers" in the object with a key of NewWelcomeMessage, to "AllUsers".
In the Azure Release "Variables" tab, can I simply use this as the "Name", Data.FeatureFlags.Preview.NewWelcomeMessage, and AllUsers as the value for it to transform the value for the correct object, or will this fail?
This pattern seems to work with XML, see this.

Best way to wrangle json data to remove field labels

I am looking to try make it easier to use the Google Analytics data in Google sheets.
The outputs that I receive from the api look like :
[
{
"dimensionValues": [
{
"value": "id2"
},
{
"value": "(not set)"
},
{
"value": "Android"
}
]
},
{
"dimensionValues": [
{
"value": "id1"
},
{
"value": "stream name"
},
{
"value": "iOS"
}
]
}
]
Whats the most efficient method to remove the field names to make a "flatter set of arrays" similar to:
[["id2","(not set)","Android"], ["id1","stream name","iOS"]]
It feels like there should be a quick way to do this!
You can use a double map for this one. Map the value to its dimensionValues and then map those to the array elements to get the designated output.
let array = [{"dimensionValues": [{"value": "id2"},{"value": "(not set)"},{"value": "Android"}]},{"dimensionValues": [{"value": "id1"},{"value": "stream name"},{"value": "iOS"}]}]
console.log(array.map(x => x.dimensionValues.map(y => y.value)))

Trouble Parsing Array vs Non-Array JSON with JSONPath

I have JSON that looks like the below. I'm trying to use JSONPath to grab the __ content __ value where the SKU is "8A-OK9F-9LI8" AND the Component.Type == 'Principal'. Right now, I am playing around with this JSON Path Expression Tester.
This JSONPath expression grabs all of the component information I need:
$.Order..Fulfillment[?(#.SKU=='8A-OK9F-9LI8')]..Component
But filtering further such as $.Order..Fulfillment[?(#.SKU=='8A-OK9F-9LI8')]..Component[?(#.Type=='Principal')] grabs only one (I believe the Array one) of the two Component elements I need. I suspect this is because one is an Array and one is a single JSON element. Is it possible to grab this with one command or do I have to combine several commands (one for the Array and one for the single JSON element)? If so, how can I grab the other Component information that I am not currently getting with:
$.Order..Fulfillment[?(#.SKU=='8A-OK9F-9LI8')]..Component[?(#.Type=='Principal')]?
Again, my goal is to grab the "__ content__" value and filter by a specific SKU and where the Component.Type == 'Principal'. Something like:
$.Order..Fulfillment[?(#.SKU=='8A-OK9F-9LI8')]..Component[?(#.Type=='Principal')]..Amount..__content__
I'm expecting to get back ["8.49", "8.49"]
Here is the JSON I am testing with:
{
"SettlementData": {},
"Order": [
{
"OrderID": "XXX",
"Fulfillment": {
"Item": {
"SKU": "8A-OK9F-9LI8",
"Quantity": "1",
"ItemPrice": {
"Component": [
{
"Type": "Principal",
"Amount": {
"__content__": "8.49",
"currency": "USD"
}
},
{
"Type": "Tax",
"Amount": {
"__content__": "0.74",
"currency": "USD"
}
}
]
}
}
}
},
{
"OrderID": "XXX",
"Fulfillment": {
"Item": {
"SKU": "8A-OK9F-9LI8",
"Quantity": "1",
"ItemPrice": {
"Component": {
"Type": "Principal",
"Amount": {
"__content__": "8.49",
"currency": "USD"
}
}
}
}
}
}
]
}
I was able to solve this in two passes. In this example, #{sku} is a Ruby interpolated string that contains the SKU I am passing in:
$.Order..Fulfillment[?(#.SKU=='#{sku}')]..ItemPrice..[?(#.Type=='Principal')].Amount.__content__
$.Order..Fulfillment..Item[?(#.SKU=='#{sku}')]..ItemPrice..[?(#.Type=='Principal')].Amount.__content__
Using a Ruby gem "jsonpath", I was able to get the amounts I needed like this:
amount = JsonPath.on(settlement, "$.Order..Fulfillment[?(#.SKU=='#{sku}')]..ItemPrice..[?(#.Type=='Principal')].Amount.__content__")
.map(&:to_f).inject(:+)
amount2 = JsonPath.on(settlement, "$.Order..Fulfillment..Item[?(#.SKU=='#{sku}')]..ItemPrice..[?(#.Type=='Principal')].Amount.__content__")
.map(&:to_f).inject(:+)

JSON array returns syntax error

I'm trying to insert an array of strings in JSON but it isn't working.
json:
{
"1": [{
"id": "1",
"title": "test 1",
"galery": { "http://placehold.it/540x540" , "http://placehold.it/540x520"}
}]
}
It's returning me syntax error on "galery" line but I can't figure out what is it
For an array, use:
"galery": ["http://placehold.it/540x540", "http://placehold.it/540x520"]
For named properties, use something like:
"galery": { url1:"http://placehold.it/540x540", url2:"http://placehold.it/540x520" }
Use [ ] for array of images in gallery. { } will expect object (key/value pairs).
You can check valid JSON syntax at http://www.json.org/
Replace the braces with brackets.
{
"1": [{
"id": "1",
"title": "test 1",
"galery": [ "http://placehold.it/540x540" , "http://placehold.it/540x520" ]
}]
}
You have incorrect syntax at two places. Below is the correct one:
{
"1": {
"id": "1",
"title": "test 1",
"galery": ["http://placehold.it/540x540" , "http://placehold.it/540x520"]
}
}

Extracting a subset of attributes with JSONPath

I have this JSON code:
{
"A": {
"AB": [{
"ABA": "0",
"ABB": "1",
"ABC": "2"
}]
}
}
I need to use a JSONPath expression that returns that JSON with only ABA and ABC attributes. Something like:
{
"A": {
"AB": [{
"ABA": "0",
"ABC": "2"
}]
}
}
So far I manage to extract either one or all attributes. For example
$.A.AB[*]
or
$.A.AB[*].ABA
Is there a way to extract only two?
Thanks
This will work using the Jayway implementation (Java):
$.A.AB[*]['ABB', 'ABA']
and the result for your input would be:
[
{
"ABB" : "1",
"ABA" : "0"
}
]
You can Compare different providers here:
http://jsonpath.herokuapp.com/