JsonPath get array element from inside other array - jsonpath

I'm just learning about JsonPath. I'm using jsonpath.com and pasting my below example in there, trying to search based on first name of Donna.
Something similar to:
$.prizes[?(#.laureates.firstname == Donna)]
but this does not work. Is it possible to use a ?(#.) kind of expression to search for firstname Donna and have the result be:
[
{
"id": "962",
"firstname": "Donna",
"surname": "Strickland",
"motivation": "\"for their method of generating high-intensity, ultra-short optical pulses\"",
"share": "4"
}
]
Original data below:
{
"prizes": [
{
"year": "2018",
"category": "physics",
"overallMotivation": "\"for groundbreaking inventions in the field of laser physics\"",
"laureates": [
{
"id": "960",
"firstname": "Arthur",
"surname": "Ashkin",
"motivation": "\"for the optical tweezers and their application to biological systems\"",
"share": "2"
},
{
"id": "961",
"firstname": "Gérard",
"surname": "Mourou",
"motivation": "\"for their method of generating high-intensity, ultra-short optical pulses\"",
"share": "4"
},
{
"id": "962",
"firstname": "Donna",
"surname": "Strickland",
"motivation": "\"for their method of generating high-intensity, ultra-short optical pulses\"",
"share": "4"
}
]
}
]
}

You're almost there; try:
$.prizes..laureates[?(#.firstname == "Donna")]

Related

Getting a specific item in a sub array and selecting one value from it

I want to get the boardgame rank (value) from this nested array in Cosmos DB.
{
"name": "Alpha",
"statistics": {
"numberOfUserRatingVotes": 4155,
"averageRating": 7.26201,
"baysianAverageRating": 6.71377,
"ratingStandardDeviation": 1.18993,
"ratingMedian": 0,
"rankings": [
{
"id": 1,
"name": "boardgame",
"friendlyName": "Board Game Rank",
"type": "subtype",
"value": 746
},
{
"id": 4664,
"name": "wargames",
"friendlyName": "War Game Rank",
"type": "family",
"value": 140
},
{
"id": 5497,
"name": "strategygames",
"friendlyName": "Strategy Game Rank",
"type": "family",
"value": 434
}
],
"numberOfComments": 1067,
"weight": 2.3386,
"numberOfWeightVotes": 127
},
}
So I want:
{
"name": "Alpha",
"rank": 746
}
Using this query:
SELECT g.name, r
FROM Games g
JOIN r IN g.statistics.rankings
WHERE r.name = 'boardgame'
I get this (so close!):
{
"name": "Alpha",
"r": {
"id": 1,
"name": "boardgame",
"friendlyName": "Board Game Rank",
"type": "subtype",
"value": 746
}
},
But extending the query to this:
SELECT g.name, r.value as rank
FROM Games g
JOIN r IN g.statistics.rankings
WHERE r.name = 'boardgame'
I get this error:
Failed to query item for container Games:
Message: {"errors":[{"severity":"Error","location":{"start":21,"end":26},"code":"SC1001","message":"Syntax error, incorrect syntax near 'value'."}]}
ActivityId: 0a0cb394-2fc3-4a67-b54c-4d02085b6878, Microsoft.Azure.Documents.Common/2.14.0
I don't understand why this doesn't work? I don't understand what the syntax error is. I tried adding square braces but that didn't help. Can some help me understand why I get this error and also how to achieve the output I'm looking for?
This should work,
SELECT g.name, r["value"] as rank
FROM Games g
JOIN r IN g.statistics.rankings
WHERE r.name = 'boardgame'

HERE geocode API latinized address

I've noticed quite severe inconsistency in result provided by HERE /geocode API endpoint. Some address parts have original special characters like in "Łódź" city and some don't.
When doing following request:
https://geocoder.cit.api.here.com/6.2/geocode.json?lon=19.4734111&lat=51.73771300000001&language=sv-SE&searchtext=sienkiewicza lodz&result_types=address,place&cs=pds&additionaldata=Country2,true
We get the result which is inconsistent
"Address": {
"Label": "ulica Henryka Sienkiewicza, 90-009 Lodz, Polen",
"Country": "POL",
"State": "Woj. Łódzkie",
"County": "Lodz",
"City": "Lodz",
"District": "Lodz",
"Subdistrict": "Śródmieście",
"Street": "ulica Henryka Sienkiewicza",
"PostalCode": "90-009",
"AdditionalData": [
{
"value": "PL",
"key": "Country2"
},
{
"value": "Polen",
"key": "CountryName"
},
{
"value": "Woj. Łódzkie",
"key": "StateName"
},
{
"value": "Lodz",
"key": "CountyName"
}
]
}
As we can see value for state contains polish characters "Woj. Łódzkie", but city is "Lodz" which is not ok.
All results should contain original letters like "Łódź". In other words such results shouldn't be latinized.
Thank you
When using a language code different than the one of the original data, like in your case sv-SE for data in Poland, you get exonyms "where available", which is why you may get a mix of alphabets.
If you remove the language parameter from the query, or set it to Polish explicitely with language=pl-PL, you get the following response for your example:
"Address": {
"Label": "ulica Henryka Sienkiewicza, 90-057 Łódź, Polska",
"Country": "POL",
"State": "Woj. Łódzkie",
"County": "Łódź",
"City": "Łódź",
"District": "Łódź",
"Subdistrict": "Śródmieście",
"Street": "ulica Henryka Sienkiewicza",
"PostalCode": "90-057",
"AdditionalData": [
{
"value": "PL",
"key": "Country2"
},
{
"value": "Polska",
"key": "CountryName"
},
{
"value": "Woj. Łódzkie",
"key": "StateName"
},
{
"value": "Łódź",
"key": "CountyName"
}
]
}

Extracting properties and meta-properties into JSON-like structure with Gremlin

My customer vertex has 4 properties and 2 meta-properties (each containing a list). The task is to return the customer data in a JSON structure. I was able to come up with this query:
g.V('customerId')
.project('customer', 'addresses', 'accounts')
.by(properties().not(hasLabel('addresses', 'accounts')).group().by(key()).by(value()))
.by(properties('addresses').valueMap().fold())
.by(properties('accounts').valueMap().fold())
which produces result
{
"customer": {
"firstName": "Carl",
"middleName": "Friedrich",
"lastName": "Gauss",
"age": 77
},
"addresses": [
{
"streetName": "View",
"streetNumber": "43",
},
{
"streetName": "Market",
"streetNumber": "11",
}
],
"accounts": [
{
"accountNumber": "1234"
},
{
"accountNumber": "4321"
}
]
}
What I actually need is a structure like this:
{
"firstName": "Carl",
"middleName": "Friedrich",
"lastName": "Gauss",
"age": 77,
"addresses": [
{
"streetName": "View",
"streetNumber": "43",
},
{
"streetName": "Market",
"streetNumber": "11",
}
],
"accounts": [
{
"accountNumber": "1234"
},
{
"accountNumber": "4321"
}
]
}
The closest I was able to get is this query:
g.V('customerId')
.properties()
.group()
.by(key)
.by(choose(hasLabel('addresses','accounts'), valueMap().fold(), value()))
which unfortunatelly groups address and account content so I can actually see only the last address/account:
{
"firstName": "Carl",
"middleName": "Friedrich",
"lastName": "Gauss",
"age": 77,
"addresses": [
{
"streetName": "Market",
"streetNumber": "11",
}
],
"accounts": [
{
"accountNumber": "4321"
}
]
}
Is there a way to list all the meta-properties elements?
For the example above,
If you add fold().unfold() it will take into account all the properties:
g.V('c81e3753-1eaa-453b-85bc-818174de70c1')
.properties()
.group()
.by(key)
.by(fold().unfold().choose(hasLabel('addresses','accounts'), value().fold(), value()))

What is the JsonPath expression for selecting an object based on sub-object values?

I need to be able to select elements within a JSON document based on the values in sub-elements which, unfortunately, reside in a list of key-value pairs (this is the structure I have to work with). I'm using Jayway 2.4.0.
Here is the JSON document:
{
"topLevelArray": [
{
"elementId": "Elem1",
"keyValuePairs": [
{
"key": "Length",
"value": "10"
},
{
"key": "Width",
"value": "3"
},
{
"key": "Producer",
"value": "alpha"
}
]
},
{
"elementId": "Elem2",
"keyValuePairs": [
{
"key": "Length",
"value": "20"
},
{
"key": "Width",
"value": "8"
},
{
"key": "Producer",
"value": "beta"
}
]
},
{
"elementId": "Elem3",
"keyValuePairs": [
{
"key": "Length",
"value": "15"
},
{
"key": "Width",
"value": "5"
},
{
"key": "Producer",
"value": "beta"
}
]
}
]
}
Here is the JsonPath I thought would do the trick:
$..topLevelArray[ ?( #.keyValuePairs[ ?(#.key=='Producer' && #.value=='beta') ] ) ]
and
$.topLevelArray[ ?( #.keyValuePairs[ ?(#.key=='Producer' && #.value=='beta') ] ) ]
Unfortunately, both are returning everything in the list, including the entry with Producer of 'alpha'. Thx in advance.

Using jq, how can I limit values based on a key

For an input file that looks like this:
{
"employees": [
{
"number": "101",
"tags": [
{
"value": "yes",
"key": "management"
},
{
"value": "joe",
"key": "login"
},
{
"value": "joe blogs",
"key": "name"
}
]
},
{
"number": "102",
"tags": [
{
"value": "no",
"key": "management"
},
{
"value": "jane",
"key": "login"
},
{
"value": "jane doe",
"key": "name"
}
]
},
{
"number": "103",
"tags": [
{
"value": "no",
"key": "management"
},
{
"value": "john",
"key": "login"
},
{
"value": "john doe",
"key": "name"
}
]
}
]
}
... I'd like to get details for all non-management employees so that the desired output looks like this:
{
"number": "102",
"name": "jane doe",
"login": "jane"
}
{
"number": "103",
"name": "john doe",
"login": "john"
}
I can't figure out how to limit results based on a key without selecting that key (in this case "management")
The following is a slightly more succinct solution:
.employees[]
| .tags |= from_entries
| select(.tags.management == "no")
| {number, "name": .tags.name, "login": .tags.login}
Using from_entries, this worked for me:
$ jq '.employees[] | {number: .number, tags: .tags | from_entries} | select(.tags.management=="no") | {number: .number, name: .tags.name, login: .tags.login}' input
... and the output is:
{
"number": "102",
"name": "jane blogs",
"login": "jane"
}
{
"number": "103",
"name": "john doe",
"login": "john"
}
There may be a better way to achieve what I wanted, so I'll leave the question open for a while if someone wants to offer a better solution.
Here is another solution which uses from_entries
.employees[]
| {number} + (.tags | from_entries)
| if .management == "no" then {number, name, login} else empty end

Resources