Manipulate Any Complex JSON with a Single JSONata Expression in Spring Boot
This article introduces JSONata4Java, shows how to add the library to a Spring Boot 3.5.0 project, and demonstrates a wide range of JSONata expressions—including property access, predicates, functions, object construction, grouping, aggregation, and sorting—through concrete code examples and expected outputs.
Introduction
In micro‑service architectures, heterogeneous JSON payloads are exchanged frequently. Hard‑coded conversion logic incurs high maintenance cost and long release cycles. JSONata4Java provides a declarative JSONata expression engine that can be configured at runtime, enabling dynamic data mapping without restarting services.
Adding the Dependency
<dependency>
<groupId>com.ibm.jsonata4java</groupId>
<artifactId>JSONata4Java</artifactId>
<version>2.6.3</version>
</dependency>The example assumes a Spring Boot 3.5.0 environment, which already includes Jackson; otherwise Jackson dependencies must be added.
Sample JSON Documents
{
"FirstName": "王强",
"Surname": "明辉",
"Age": 28,
"Address": {
"Street": "科技园路88号",
"City": "深圳市",
"Postcode": "518057"
},
"Sno": [2,4,6,8,10],
"Phone": [
{"type":"home","number":"0755-8888 1234"},
{"type":"office","number":"0755-6666 1234"},
{"type":"office","number":"0755-6666 1235"},
{"type":"mobile","number":"138 0000 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": "中山路168号",
"City": "上海市",
"Postcode": "200001"
}
}
} {
"Account": {
"Order": [
{
"Product": [
{"Product Name":"Bowler Hat","Price":34.45,"Quantity":2},
{"Product Name":"Trilby hat","Price":21.67,"Quantity":1}
]
},
{
"Product": [
{"Product Name":"Bowler Hat","Price":34.45,"Quantity":4},
{"Product Name":"Cloak","Price":107.99,"Quantity":1}
]
}
]
}
}Basic Operations
Evaluating simple path expressions:
expression = "FirstName";
result = expressions.evaluate(jsonNode);
// Output: "王强"
expression = "Address.City";
// Output: "深圳市"
expression = "Phone[0]";
// Output: {"type":"home","number":"0755-8888 1234"}
expression = "Phone[0].number";
// Output: "0755-8888 1234"
expression = "Phone.number[0]";
// Output: ["0755-8888 1234","0755-6666 1234","0755-6666 1235","138 0000 1234"]
expression = "Phone[[0..1]]";
// Output: [{"type":"home","number":"0755-8888 1234"},{"type":"office","number":"0755-6666 1234"}]Predicate Queries
Filtering with boolean predicates:
expression = "Phone[type='mobile']";
// Output: {"type":"mobile","number":"138 0000 1234"}
expression = "Phone[type='office'].number";
// Output: ["0755-6666 1234","0755-6666 1235"]
expression = "Address.*";
// Output: ["科技园路88号","深圳市","518057"]
expression = "*.Postcode";
// Output: "518057"Functions & Expressions
String concatenation uses &. Numeric operators follow standard arithmetic.
expression = "FirstName & ' ' & Surname";
// Output: "王强 明辉"
expression = "Address.(Street & ', ' & City)";
// Output: "科技园路88号, 深圳市"
expression = "Sno[0] + Sno[1]";
// Output: 6
expression = "Sno[0] > Sno[1]";
// Output: FALSE
expression = "(Sno[2] != 4) and (Sno[3] != Sno[4])";
// Output: TRUEObject Construction
expression = "Email.[address]";
// Output: [["[email protected]","[email protected]"],["[email protected]","[email protected]"]]
expression = "[Address, Other.`Alternative.Address`].City";
// Output: ["深圳市","上海市"]
expression = "Phone.{type: number}";
// Output: [{"home":"0755-8888 1234"},{"office":"0755-6666 1234"},{"office":"0755-6666 1235"},{"mobile":"138 0000 1234"}]Grouping & Aggregation
expression = "Account.Order.Product{`Product Name`: Price}";
// Output: {"Bowler Hat":[34.45,34.45],"Trilby hat":21.67,"Cloak":107.99}
expression = """
Account.Order.Product {
`Product Name`: {"Price": Price, "Qty": Quantity}
}
""";
// Output: {"Bowler Hat":{"Price":[34.45,34.45],"Qty":[2,4]},"Trilby hat":{"Price":21.67,"Qty":1},"Cloak":{"Price":107.99,"Qty":1}}
expression = "Account.Order.Product{`Product Name`: $.(Price*Quantity)}";
// Output: {"Bowler Hat":[68.9,137.8],"Trilby hat":21.67,"Cloak":107.99}
expression = "$sum(Account.Order.Product.Price)";
// Output: 198.56Array Functions
expression = "$count([1,2,3,1])";
// Output: 4
expression = "$append([1,2,3],[4,5,6])";
// Output: [1,2,3,4,5,6]Sorting Example
expression = """
$sort(Account.Order.Product, function($l, $r) {
$l.Price * $l.Quantity > $r.Price * $r.Quantity
})
""";
// Result: [{"Product Name":"衬衣","Price":88,"Quantity":2},{"Product Name":"西裤","Price":230,"Quantity":1},{"Product Name":"内衣","Price":121,"Quantity":3}]Reference
Complete list of JSONata functions and syntax: https://docs.jsonata.org/
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
