This project provides an Open Source implementation of the language JSONata 2 created by Andrew Coleman.
Promising to keep the compatibility with the JSONata 2 grammar, this project extends the grammar aiming to provide an useful language for ETL operations and workflow definition.
This implementation was created purely from the JSONata language specifications without any debt from any previous implementation, notably the JavaScript JSONata project and IBM JSONata4Java project to allow the most permissive use of the code.
The author of the project strongly believes
It is through art, and through art only, that we can realise our perfection. (Oscar Wilde)
without being obsessed if the perfection quoted is our or not, just happy to be in search of it, returning to community of developers a drop of what he withdrew in many years of career. Art is a gift, a gift should be free from the reciprocation, whatever Claude_Lévi-Strauss wrote about, albeit about different contexts.
This project uses ANTLR 4 to define the JSONata grammar and to generate its parser. The language processor is implemented in the Kotlin 1.8 language.
The project is published in Maven Central. comopplete of source code and documentation jars.
Declere dependency on it according the building toolchain of your choice.
implementation 'io.github.lucanicoladebiasi:jsong:1.1'
implementation("io.github.lucanicoladebiasi:jsong:1.1")
<dependency>
<groupId>io.github.lucanicoladebiasi</groupId>
<artifactId>jsong</artifactId>
<version>1.1</version>
</dependency>
Kotlin is handy to declare JSON objects.
Suppose to define an address
object as explained in the Simple Queries page
of the official JSONata documentation: in Kotlin this is defined as follows.
@Language("JSON")
val root: JsonNode = mapper.readTree(
"""
{
"FirstName": "Fred",
"Surname": "Smith",
"Age": 28,
"Address": {
"Street": "Hursley Park",
"City": "Winchester",
"Postcode": "SO21 2JN"
},
"Phone": [
{
"type": "home",
"number": "0203 544 1234"
},
{
"type": "office",
"number": "01962 001234"
},
{
"type": "office",
"number": "01962 001235"
},
{
"type": "mobile",
"number": "077 7700 1234"
}
],
"Email": [
{
"type": "work",
"address": ["[email protected]", "[email protected]"]
},
{
"type": "home",
"address": ["[email protected]", "[email protected]"]
}
],
"Other": {
"Over 18 ?": true,
"Misc": null,
"Alternative.Address": {
"Street": "Brick Lane",
"City": "London",
"Postcode": "E1 6RF"
}
}
}
""".trimIndent()
)
To evaluate the JSONata expression Address.City
to the JSON object addreess
, the code is as simple as
val expression = "Address.City"
val result = Processor(root).evaluate(expression)
where
root
is theJsonNode
object to evaluate with the JSONataexpression
,root
can benull
;expression
is a string being a valid JSONata statement;result
returns the outcome ofexpression
applied toroot
, it is aJsonNode
object and it can benull
. For the above example,result
is aTextNode
wrapping "Winchester" string.
JUnit tests are organized per page of the JSONata official documentation, please, refer to them for a rich set of examples about how to use this software.
The code is documented: start reading the documentation of the io.github.lucanicoladebiasi.jsong.Processor
class.
The order-by path operator is full implemented.
- Operators
- The transform operator (planned for 1.2 release).
- Functions
- $formatInteger() doesn't implement the JS
picture
argument. - $formatNumber() doesn't implement the
options
argument. - $fromMillis() doesn't implement the JS
picture
argument. - $parseInteger() doesn't implement the
options
argument. - $replace() doesn't implement the
limit
argument, thereplacement
doesn't parse the regex group reference. - $toMillis() doesn't implement the JS
picture
argument.
- $formatInteger() doesn't implement the JS
This tiny project is my attempt to return a little of what I received from the open-source community, hence feel free to fork, criticize (nothing can offend me, I will always learn from your observations), improve, propose.
To decide what next to release, please, write an e-mail to [email protected]
with subject line
starting with "JSong": we will decide how to merge your contribution.
Copyright (c) 2023 Luca Nicola Debiasi
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.