I had a need recently to express a conditional expression in a form that a front end Javascript application and a backend Java application could both create and read. Expressing the conditional expression as a Json felt logical and after a quick search, JsonLogic library appeared to fit exactly what I was looking for.
JsonLogic follows a prefix notation for its expressions, along these lines:
{"operator" : ["values" ... ]}So for eg, given a JSON input data that looks like this:
{For equality, an expression using JsonLogic is the following:
"a": "hello",
"b": 1,
"c": [
"elem1",
"elem2"
]
}
{"==" : [ { "var" : "a" }, "hello" ] }Here the data is being looked up using "var" expression and the equality is checked using the "==" operator.
Though it is a good fit, I decided to go with an alternate way of expressing the conditional expression but heavily inspired by JsonLogic. So, in my implementation, equality with the sample JSON looks like this:
{Fairly similar, the location to the data is expressed as a Json Pointerand the operators are textual ("equals" vs "==") The full set of supported features are also much smaller than JsonLogic as that sufficed my needs for the project. So now I have a small Java-based library that supports these simplified conditional expressions and this post will go into the details of the operators and the usage of the library.
"equals": [
"/a", "hello"
]
}
Sample Expressions
Once more to touch on the sample conditional expressions, everything takes the form of:{"operator" : ["values" ... ]}A check for equality looks like this:
{Not operator:
"equals": [
"/a", "hello"
]
}
{And/Or operator:
"not": [
{
"equals": [
"/a",
"hello"
]
}
]
}
{There are a few operators that work on collections, for eg, to check if "c" in the sample JSON has elements "elem1", "elem2":
"and": [
{
"equal": [
"/a", "hello"
]
},
{
"equal": [
"/b", 1
]
}
]
}
{or to check if the collection has any of the elements "elem1", "elem2":
"contains": [
"/c", ["elem1", "elem2"]
]
}
{
"containsAnyOf": [
"/c", ["elem1", "elem2"]
]
}
Details of the Library
The Java-based library is built on top of the excellent Jackson JSON parser library and uses it to parse the expression which once parsed is interpreted by the library. A Gradle based project can pull in the dependency the following way(published currently to JCenter):implementation 'com.github.bijukunjummen:json-conditional-expression:0.4.0'and use the library along these lines, using a sample Kotlin code:
val jsonExpressionEvaluator: JsonExpressionEvaluator = JsonExpressionEvaluator(ObjectMapper())
jsonExpressionEvaluator.matches(expression, json) //returns true
Conclusion
The conditional expression and the corresponding Java-based interpreter are fairly simple and have sufficed my needs with the kind of operators that I needed for my project, however, I will be more than happy to extend and support more extensive operators if there is enough interest in using the library.Reference
1. JsonLogic which provided the inspiration for using a prefix notation to represent a conditional expression2. The project resides in GitHub here - https://github.com/bijukunjummen/json-conditional-expression