How to get this using json path? - jsonpath

{
"store": {
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
},
"expensive": 10
}
What if I need both author and title of all the books? Like rather than having the complete data about the book if I only want some detail of it how can I get that?

Depending on the implementation, this
$..book[*]['title','author']
should get you close enough.

Related

Find most expensive book using JSONPath

Given the Goessner example JSON:
{
"store": {
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}
I can get the highest price for a book using the following query:
$.max($.store.book[*].price)).
Response: 22.99.
If I query for this price: $.store.book[?(#.price ==22.99)]
Response:
[
{
"category" : "fiction",
"author" : "J. R. R. Tolkien",
"title" : "The Lord of the Rings",
"isbn" : "0-395-19395-8",
"price" : 22.99
}
]
But trying to inline the max expression into the query only gives a syntax error:
$.store.book[?(#.price ==$.max($.store.book[*].price)))]
Is this possible in a single JSONPath query?
In Jayway JSONPath Functions can be invoked at the tail end of a path
$.store.book[?(#.price == $..book[*].price.max())]
Online Tool : https://jsonpath.herokuapp.com/
Note : may not work with other implementations.

JSON Path - is there a way to only return a specific number of filtered elements?

I'm pretty sure there isn't a way to do this purely with JSON path, but figured I'd ask any how.
When applying a filter on an array within the object, is there a way to specify to return only the first n elements?
e.g., working of the example from https://goessner.net/articles/JsonPath/
Given an object like this:
{ "store": {
"book": [
{ "category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{ "category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{ "category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{ "category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}
and running a JSON path expression like so:
$..book[?(#.price<10)]
Will return 2 objects:
[
{
"category" : "reference",
"author" : "Nigel Rees",
"title" : "Sayings of the Century",
"price" : 8.95
},
{
"category" : "fiction",
"author" : "Herman Melville",
"title" : "Moby Dick",
"isbn" : "0-553-21311-3",
"price" : 8.99
}
]
Is there any syntax that results in JSON Path only returning 1 of the objects?
There isn't a function on it's own. I would work around this like so...
const filterBooks = $..book[?(#.price<10)]
const firstBook = $.. filterBooks[0]
const lastBook = $.. filterBooks[-1:]

Want "null" printed

Let's say I have this data sample:-
{
"store": {
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"color": "red",
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"author": "Herman Melville",
"color": "blue",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
},
"expensive": 10
}
If I look up for the JsonPath $.store..isbn
I get back :-
[
"0-553-21311-3",
"0-395-19395-8"
]
What I want is :-
[
null,
null,
"0-553-21311-3",
"0-395-19395-8"
]
Could someone tell if this is possible in JsonPath and if not, are there any alternatives?
You can try to compare results length and data length, then push needed amounts of null in the head of array.
Using Configuration you can achieve it.
Need to set Option.DEFAULT_PATH_LEAF_TO_NULL option in configurations, it will return null if node in not there
Complete example would be:
ReadContext ctx=JsonPath.using(Configuration.builder().options(Option.DEFAULT_PATH_LEAF_TO_NULL).build()).parse(jsonData);
System.out.println(ctx.read("$.store.book..isbn"));
Output:
[null,null,"0-553-21311-3","0-395-19395-8"]

DEFAULT_PATH_LEAF_TO_NULL Tweaking Configuration in Jayway JsonPath doesnot return null for inner arrays

I have a json string like:
{
"store": {
"book": [
{
"category": "reference",
"authorextra": [
{
"auth1":"Nigel Rees",
"auth2":"xxxx"
}
],
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
},
"expensive": 10
}
I have used the DEFAULT_PATH_LEAF_TO_NULL option while parsing the json.
ReadContext ctx=JsonPath.using(Configuration.builder().options(Option.DEFAULT_PATH_LEAF_TO_NULL).build()).parse(input);
When i read this path :
returnObj = ctx.read($.store.book[*].authorextra[*].auth1);
I get the result as :
[
"Nigel Rees"
]
I am expecting :
[
"Nigel Rees",
null,
null,
null
]
What configuration am i missing here? Any help is appreciated. TIA !
I think you have overlooked the LEAF part of the DEFAULT_PATH_LEAF_TO_NULL setting. Your path has store --> book --> authorextra --> auth1. So the leafs that will be set to NULL are those auth1 missing for authorextra. As the first book is the only one having authorextra, it is the only one giving you result, as it is the only one where you can look for a leaf. If you try this other json document:
{
"store" : {
"book" : [
{
"category" : "reference",
"authorextra": [
{
"auth1":"Nigel Rees",
"auth2":"xxxx"
}
],
"title" : "Sayings of the Century",
"price" : 8.95
},
{
"category" : "fiction",
"authorextra": [
{
"auth2":"Evelyn Waugh"
}
],
"title" : "Sword of Honour",
"price" : 12.99
},
{
"category" : "fiction",
"author" : "Herman Melville",
"title" : "Moby Dick",
"isbn" : "0-553-21311-3",
"price" : 8.99
},
{
"category" : "fiction",
"author" : "J. R. R. Tolkien",
"title" : "The Lord of the Rings",
"isbn" : "0-395-19395-8",
"price" : 22.99
}
],
"bicycle" : {
"color" : "red",
"price" : 19.95
}
},
"expensive" : 10
}
You would get ["Nigel Rees", null], because the second book also has authorextra, but has missing auth1, that is, the leaf.

Trouble composing jsonpath query to return first object of a filtered array

Using the ashphy json path evaluator, and the following JSON:
{ "store": {
"book": [
{ "category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{ "category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{ "category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{ "category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}
I would like to write a query that filters category, e.g. "fiction", and then return only the first element. I can't quite seem to figure it out.
For example, $..book[?(#.category == "fiction")], will return an array of 3 books, but I just want the first book:
{ "category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
}
Can it be done?? The obvious thing seemed to be to add an "[0]" to the end, but it does not work.
I examined the analytics site (Note: this is from testing http://ashphy.com/JSONPathOnlineEvaluator/):
Placing the [0] index look up DOES work. The site merely accepts what will go inside the argument of jsonPath(jsonObj, query string) thus the index reference must go outside this evaluation which the site does not do.
jsonPath(foo, '$..book[?(#.category == "fiction")]')[0]

Resources