This library extends JsonPath for direct logical operations on JSON data. It allows complex querying and filtering within JSON structures using an extended syntax with logical operators.
Library is available in the Central Maven Repository. You can find the latest version under the "sonatype-central" badge at the top of the README.
implementation("org.ilinykh.kotlin.logic-json-path:logic-json-path:1.0.0")
implementation 'org.ilinykh.kotlin.logic-json-path:logic-json-path:1.0.0'
<dependency>
<groupId>org.ilinykh.kotlin.logic-json-path</groupId>
<artifactId>logic-json-path</artifactId>
<version>1.0.0</version>
</dependency>
val json = """some JSON here""".trimIndent()
val exp = Expression("#\$.payload.first.value#\$.payload.second.value#=")
Result(json, exp).result()
Operator | Description | Constraints |
---|---|---|
= | Equals. Left is equal to right |
Boolean types works case insensitive, otherwise works as string compare. |
!= | Not Equals. Left is NOT equal to right. |
Boolean types works case insensitive, otherwise works as string compare. |
& | AND | Numbers only. |
| | OR | Numbers only. |
< | Less Than Left element is less to right. |
Numbers only. |
<= | Less Or Equal. Left element is less or equal to right. |
Numbers only. |
> | Greater Than. Left element is greater to right. |
Numbers only. |
>= | Greater Or Equal. Left element is greater or equal to right. |
Numbers only. |
+ | Plus. Sum of left and right elements. | Numbers only. Returns the most scale of operands. |
- | Minus. Left element minus right element. | Numbers only. Returns the most scale of operands. |
* | Multiply. Multiplication of left and right elements. | Numbers only. Returns the most scale of operands. RoundingMode.HALF_UP. |
/ | Divide. Division left element to right element. | Numbers only. Returns the most scale of operands. RoundingMode.HALF_UP. |
Expressions must be declared in reverse polish notation (RPN).
Separate each element with a #
symbol.
Correct: #10#11#>#12#13#<#=
in infix form this expression equivalent is (10>11)=(12<13)
Incorrect: #10#11#>#12#13#>
. You can't use comparison operations on the boolean type.
Let's write expression for JSON below.
{
"payload": {
"first": {
"value": true
},
"second": {
"value": false
}
}
}
Task: compare two boolean fields and return true if they're same and false if not.
Expression: "#$.payload.first.value#$.payload.second.value#="
Result: false
Explanation: We can tokenize this expression:
$.payload.first.value
- first element (json-path)$.payload.second.value
- second element (json-path)=
- operation under elements
After replacing to values token stack looks like:
- true
- false
- =
After making operation over stack we get result false
You also can make huge expressions with multiple elements. In this case RPN might me slight difficult to understand.
{
"payload": {
"first": {
"value": true
},
"second": {
"value": false
},
"third": {
"value": true
}
}
}
Task: Return true if three elements are the same; otherwise false.
Expression (in infix pseudocode): (payload.first.value = payload.second.value) & (payload.first.value = payload.third.value)
Expression (RPN): #$.payload.first.value#$.payload.second.value#=#$.payload.first.value#$.payload.third.value#=#&
Tokens:
$.payload.first.value
- first element (json-path)$.payload.second.value
- second element (json-path)=
- operation under elements$.payload.first.value
- first element (json-path)$.payload.third.value
- third element (json-path)&
- operation under elements
Result: false
You also can use internal json-path functions.
{
"store": {
"book": [
{
"title": "Sayings of the Century",
"price": 8.95
},
{
"title": "Sword of Honour",
"price": 12.99
},
{
"title": "Moby Dick",
"price": 8.99
},
{
"title": "Cipollino",
"price": 22.99
}
]
}
}
Task: calculate price and return true if price sum is less than 100.
Expression: #$.sum($.store.book[*].price)#100#<
Tokens:
$.sum($.store.book[*].price)
- first element (json-path function)100
- second element 3<
- operation under elements
Result: true
Explanation:
$.store.book[*].price
maps json into array[8.95, 12.99, 8.99, 22.99]
.$.sum($.store.book[*].price)
- sum array and return value53,92
100<
- compare previous value53,92
with100
. In infix form this is equivalent for53,92 < 100
- Return
true