JsonPath: How to get the whole tree except one node - java

everyone.
My question is quite simple, I think.
My use case:
Jenkins receives a huge JSON payload from a Gitlab WebHook (more than 2500 lines). I want to get rid of a specific node with more than 2000 lines. The JSON I get is so big that Jenkins is unable to parse it correctly so I want to remove a node I don't need.
Assume the sample tree in the documentation page:
{
"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
}
How can I get the whole tree except one? For example, if I want to get everything but the book node ...
{
"store": {
"bicycle": {
"color": "red",
"price": 19.95
}
},
"expensive": 10
}
I more or less understand the filters feature, and I assume I need to figure out a proper filter but it seems they are only useful to search nodes based on some criteria. I'm not sure if they are useful to remove elements based on filtering conditions.
Thanks so much for your help.

JSON Path is a tool for querying, not manipulation. You're not going to be able to alter the input value with it. You need another tool.
I'd suggest looking at something like https://jsonnet.org/ which is designed for template-based transformations and generation.

Related

how to compare each element in array?

{
"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
}
]
}
}
The following is my case:
author=='Nigel Rees'.price < author=='Evelyn Waugh'.price
My query expression: $.store.book[?($.store.book[?(#.author == 'Nigel Rees')].price < $.store.book[?(#.author == 'Evelyn Waugh')].price)]
I hope it will return the following result:
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
}
What is the correct expression?
Ordinarily, to iterate over the items in an array and perform a comparison, you'd need to use a filter selector:
$.store.books[?(#.price<12.99)]
But this doesn't allow you to compare items against each other. Within that expression, you should (may depend on the library you're using) be able to use the $ to refer back to the JSON root. This would allow you to make a comparison against a particular item:
$.store.books[?(#.price<$.store.books[1].price)]
This compares all of the book prices against the price of the second book in the array. I think this is the closest you're going to get with JSON Path.
We're currently working on a specification for JSON Path to define an official syntax and feature set. Feel free to open an issue (and link to this question) to request "multiple iterator" support so that items can be compared against each other.

Filter values by regex in JsonPath

I was trying to find a way to filter values by regex using JsonPath from Jayway and so far I could more or less do what I want to do.
I'm trying to filter results by values which does not start with 'foo'. To my regex knowledge it should be done by '$..book[?(#.author =~ /^[^foo]/)].author' with the given JSON of
{
"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
}
but it doesn't return any values although none of the values are not starting with 'foo'. I've tried it via using the online tool: https://jsonpath.herokuapp.com/
In addition, I can't solve this problem with any Java code or Filters that would be written in Java or similar. Regex would be my more or less only choice here.
Anybody knows how to solve this problem?
Cheers,
to filter results by values which does not start with 'foo', try: $..book[?(#.author =~ /^(?!foo).*/i)]
Regex: /^(?!foo).*/i) returns a match only if it doesn't start with foo (using negative lookahead)

GPath on nested objects

I'm not sure what I'm doing wrong here and I'm having a hell of a time with getting this to work properly. Using this JSON:
{
"books": [
{
"category": "reference",
"author": {
"name": "Nigel Rees",
"age": 45
},
"title": "Sayings of the Century",
"price": 8.95,
"tax": 7.00
},
{
"category": "reference",
"author": {
"name": "Evelyn Waugh",
"age": 30
},
"title": "A cheap book",
"price": 6.00,
"tax": 3.00
}
]
}
I'm not able to extract the books where the authors age is 45, for example. I've tried things like the following (with the books document root set)
findAll {it.author.age == 45}
findAll {it.author}.findAll {it.age == 45}
findAll {it.author}*.each {it.age == 45 }
I still get back all of the records that have an age item. It can be any arbitrary object, it might not have an author record, etc. And I want the root book object returned.
I feel like there's something really obvious I'm missing, but the docs seem to only cover one level of key-values. Maybe it doesn't support it?
Thanks!
here is it
books.findAll{it.author.age==45}
It's not working your way (findAll {it.author.age == 45}) because you work from the root, and 'it' variable returns 'books' object, which has no field 'author'.

Remove selected nodes from a JSON stream

I need to serve JSON from from my backend to the user. But before sending it over the wire I need to remove some data because it's confidential, every element who's key starts with conf_.
Assume I have the following JSON source:
{
"store": {
"book": [
{
"category": "reference",
"conf_author": "Nigel Rees",
"title": "Sayings of the Century",
"conf_price": 8.95
},
{
"category": "fiction",
"conf_author": "Evelyn Waugh",
"title": "Sword of Honour",
"conf_price": 12.99
},
{
"category": "fiction",
"conf_author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"conf_price": 8.99
},
{
"category": "fiction",
"conf_author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"conf_price": 22.99
}
],
"bicycle": {
"color": "red",
"conf_price": 19.95
}
},
"expensive": 10
}
Since the structure of the soruce JSON may vary (is not known), I need a way to identify the elements to remove by a pattern based on the key name (^conf_).
So the resulting JSON should be:
{
"store": {
"book": [
{
"category": "reference",
"title": "Sayings of the Century"
},
{
"category": "fiction",
"title": "Sword of Honour"
},
{
"category": "fiction",
"title": "Moby Dick",
"isbn": "0-553-21311-3"
},
{
"category": "fiction",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8"
}
],
"bicycle": {
"color": "red"
}
},
"expensive": 10
}
Since my source JSON will have 1m+ entries in the books array where every entry will have 100+ fields (child objects), I'm looking for some stream / event based approach like StAX rather then parsing the whole JSON into a JSONObject for manipulation for performance and resource reasons.
I looked at things like Jolt, JSONPath and JsonSurfer but these libraries did me get anywhere so far.
Can anyone provide some details on how my use case could be implemented best?
Regards!
You can use Jackson's Streaming API which can be used to parse huge JSON upto even giga bytes of size.It can be used to process huge files without loading them completely in memory.It allows get the data you want and ignore what you don't want also
Read more: http://wiki.fasterxml.com/JacksonStreamingApi

How to search inside a json file?

I have a JSON file with content like so :
[
{
"Name": "A+",
"Type": "Array",
"Designed by": "Arthur Whitney"
},
{
"Name": "Ada",
"Type": "Compiled, Imperative, Procedural, Object-oriented class-based",
"Designed by": "Tucker Taft, Jean Ichbiah"
}
{
"Name": "C",
"Type": "Compiled, Curly-bracket, Imperative, Procedural",
"Designed by": "Dennis Ritchie"
},
{
"Name": "C#",
"Type": "Compiled, Curly-bracket, Iterative, Object-oriented class-based, Reflective, Procedural",
"Designed by": "Microsoft"
},
{
"Name": "Java",
"Type": "Compiled, Curly-bracket, Imperative, Object-oriented class-based, Procedural, Reflective",
"Designed by": "James Gosling, Sun Microsystems"
},
{
"Name": "JavaScript",
"Type": "Curly-bracket, Interpreted, Reflective, Procedural, Scripting, Interactive mode",
"Designed by": "Brendan Eich"
}
]
I want to write a web application that user type a word FOR EXAMPLE "java" in a textbox and then click the search button .after that search inside this JSON file and show the result in a web page .
I am new in a web application.I don't know how to search through a JSON file and represent the result .Can anyone help me?
If you just want to get the job done, you can use lodash and than simply do something like this:
var data = [...] // your jsonfile as array of objects
_.findWhere(data, {Name:"Java"}) // returns the object

Categories