简介:一个能够通过JSON配置(特定的语法)来处理复杂数据转换的工具。
比如将API响应转换为内部系统所需的格式,或者处理来自不同来源的数据结构差异。例如,将嵌套的JSON结构扁平化,或者重命名字段,合并多个字段等。
名称含义:
-
JSON + Bolt:
JSON 是工具处理的数据格式。
Bolt(闪电)象征快速和高效,暗示 Jolt 能够像闪电一样快速完成 JSON 数据的转换。
Bolt的logo就是一个闪电⚡️标志 -
在社区中,Jolt 的名称被解读为 JSON Transformation Language 的缩写,强调其作为 JSON 转换语言的定位。
-
项目地址:https://github.com/bazaarvoice/jolt
-
在线验证工具:https://jolt-demo.appspot.com/#inception
使用
1. 引入maven依赖
- pom.xml
<dependency>
<groupId>com.bazaarvoice.jolt</groupId>
<artifactId>jolt-core</artifactId>
<version>0.1.7</version>
</dependency>
<dependency>
<groupId>com.bazaarvoice.jolt</groupId>
<artifactId>json-utils</artifactId>
<version>0.1.7</version>
</dependency>
2. 编写Jolt转换规范(json格式)
- spec.json
[
{
"operation": "shift",
"spec": {
"id": "id",
"orderType": "type",
"orderProductList": {
"*": {
"sampleNumber": "orderProductList[&1].number",
"id": "orderProductList[&1].id"
}
},
"createTime": "createTime"
}
},
{
"operation": "modify-overwrite-beta",
"spec": {
"id": "=toString(@(1,id))",
"createTime": "=concat(@(1,createTime), ' 00:00:00')"
}
}
]
3. Java集成示例
- DataTransformTool
import com.bazaarvoice.jolt.Chainr;
import com.bazaarvoice.jolt.JsonUtils;
import java.util.List;
/**
* description: DataTransformTool <br>
* date: 2025/3/13 11:47 <br>
* author: Boo <br>
* version: 1.0 <br>
*/
public class DataTransformTool {
public static String transform(String inputJson, String specPath) {
List chainrSpecJSON = JsonUtils.classpathToList( specPath );
Chainr chainr = Chainr.fromSpec( chainrSpecJSON );
Object transformedOutput = chainr.transform( JsonUtils.jsonToObject(inputJson) );
return JsonUtils.toJsonString( transformedOutput );
}
}
- Test.java
public static main(String[] args) {
String inputJson = "{" +
" \"id\": 123456789," +
" \"orderType\": \"orderTypecsss\"," +
" \"orderProductList\": [" +
" {\"sampleNumber\": \"number001\", \"id\": 2}," +
" {\"sampleNumber\": \"SKU456\", \"id\": 1}" +
" ]," +
" \"createTime\": \"2025-03-13\"" +
" }";
System.out.println(DataTransformTool.transform(inputJson, "spec.json"));
}
- 运行结果
{
"id": "123456789",
"type": "orderTypecsss",
"orderProductList": [
{
"number": "number001",
"id": 2
},
{
"number": "SKU456",
"id": 1
}
],
"createTime": "2025-03-13 00:00:00"
}
Jolt 转换规范的核心语法
AI整理,仔细辨别
核心操作类型
操作类型 | 用途 | 示例 |
---|---|---|
shift | 字段映射/结构调整 | “oldField”: “newField” |
modify-overwrite-beta | 数据修改(类型转换/计算) | “field”: “=toUpper” |
default | 设置默认值 | “field”: “defaultVal” |
remove | 删除字段 | “fieldToRemove”: “” |
sort | 字段排序 | 无参数,直接使用 |
核心操作符及示例
1. shift
用途:字段重映射、结构调整。
语法:将输入路径映射到输出路径。
示例:
{
"operation": "shift",
"spec": {
"inputField": "output.parent.child", // 简单映射
"nested.input.value": "output.value", // 嵌套映射
"array[*].id": "output.ids[]" // 数组展开
}
}
2. default
用途:设置默认值(字段不存在时生效)。
语法:
{
"operation": "default",
"spec": {
"output.role": "guest", // 单值默认
"output.tags": ["default"] // 数组默认
}
}
3. remove
用途:删除指定字段。
语法:
{
"operation": "remove",
"spec": {
"unusedField": "", // 删除字段
"nested.tempData": "" // 删除嵌套字段
}
}
4. sort
用途:按字母序排序对象键。
语法:
{ "operation": "sort" }
5. cardinality
用途:强制字段为单值或数组。
语法:
{
"operation": "cardinality",
"spec": {
"output.roles": "array", // 强制为数组
"output.name": "single" // 强制为单值
}
}
6. modify-overwrite-beta
用途:覆盖或修改字段值(需 Jolt 扩展库)。
语法:
{
"operation": "modify-overwrite-beta",
"spec": {
"output.score": "=toDouble(@(1,input.score))" // 转换为浮点数
}
}
7. modify-default-beta
用途:条件默认值(类似 default 但支持表达式)。
语法:
{
"operation": "modify-default-beta",
"spec": {
"output.status": "=if (isPresent(@(1,input.status))) then @(1,input.status) else 'pending'"
}
}
路径语法规则
点号.:表示嵌套字段,如 user.address.city。
通配符*:匹配任意字段或数组元素:
users[].name:提取所有 users 元素的 name。
data..value:匹配 data 下的所有子字段的 value。
数组索引[n]:定位数组的特定位置,如 items[0].id。
转义\:若字段名包含 . 或 *,需转义,如 field\.with\.dots。
链式操作示例
json
[
// 第一步:字段映射
{
"operation": "shift",
"spec": {
"firstName": "user.name",
"age": "user.details.age"
}
},
// 第二步:添加默认值
{
"operation": "default",
"spec": {
"user.role": "guest",
"user.details.active": true
}
},
// 第三步:删除冗余字段
{
"operation": "remove",
"spec": {
"user.details.age": ""
}
}
]
输入:
{ "firstName": "John", "age": 30 }
输出:
{
"user": {
"name": "John",
"role": "guest",
"details": {
"active": true
}
}
}
高级技巧
- 动态键名:使用 & 引用输入字段的值作为键:
{
"operation": "shift",
"spec": {
"userType": "output.&" // 将 userType 的值作为键
}
}
输入 { “userType”: “admin” } → 输出 { “output”: { “admin”: “admin” } }。
- 条件逻辑:通过 modify 系列操作符实现复杂条件:
{
"operation": "modify-overwrite-beta",
"spec": {
"output.discount": "=if (@(1,price) > 100) then 0.1 else 0"
}
}
- 数组聚合:将多个字段合并为数组:
{
"operation": "shift",
"spec": {
"tags": "output.tags[]"
}
}
注意事项
- 大小写敏感:字段名和路径严格区分大小写。
- 路径不存在:若输入路径不存在,操作符会静默忽略。
- 性能优化:复杂嵌套或通配符可能影响性能,尽量简化规则。