joi使用

这是一个jolt 使用教程的项目 Jolt是用Java编写的JSON到JSON转换库,可以将我们输入的一个json,转换成目标json. jolt官网传送门 官网地址. 详细使用教程可以访问本人如下开源项目 github jolt教程 开源项目 jolt-universe. gitCode jolt 教程 开源项目 jolt-universe gitee 码云 jot教程 开源项目

这是一个jolt 使用教程的项目

Jolt是用Java编写的JSON到JSON转换库,可以将我们输入的一个json,转换成目标json.
jolt官网传送门 官网地址.
详细使用教程可以访问本人如下开源项目
github jolt教程 开源项目 jolt-universe.
gitCode jolt 教程 开源项目 jolt-universe
gitee 码云 jot教程 开源项目 jolt-universe.

开源项目会持续更新,为大家带来更全、更好的jolt用法教程,如果大家有什么疑问,或者有什么需要转换json,可以在issues 中注明 input(输入),和Output(输出),
大家可以一起探讨交流。
文中如有描述错误,请及时留言指出。如有转载,请标明出处。

在线调试工具

在线调试工具 传送门地址.
你可以将json数据和jolt表达式在上面运行,由于这个在线工具是托管在 Google App Engine 上面的,国内的网络可能无法访问
image

入门教程

快速入门

1在maven中添加 jolt的依赖

<dependency>
    <groupId>com.bazaarvoice.jolt</groupId>
    <artifactId>jolt-core</artifactId>
    <version>0.1.6</version>
</dependency>
<dependency>
    <groupId>com.bazaarvoice.jolt</groupId>
    <artifactId>json-utils</artifactId>
    <version>0.1.6</version>
</dependency>

目前最新的版本为0.1.6 具体的版本号可以查看这里 jolt历史版本.

以下是具体的demo ShiftTest.java

演示demo

package com.example.demo.shift;

import com.bazaarvoice.jolt.Chainr;
import com.bazaarvoice.jolt.JsonUtils;
import org.junit.jupiter.api.Test;

import java.util.List;

public class ShiftTest {

    /**
     * 测试demo
     */
    @Test
    public void testDemo() {
         //将json字符串转成object 对象
        Object input = JsonUtils.classpathToObject("/json/sample/input.json");
        //将json字符串转成List 对象
        List spec = JsonUtils.classpathToList("/json/sample/spec.json");
        Chainr chainr = Chainr.fromSpec(spec);
        //转换结果
        Object transform = chainr.transform(input);
        System.out.println(JsonUtils.toJsonString(transform));
    }
}

/json/sample/input.json

数据json文件

{
    "orderId": 1212,
    "orderNo":"202223434343",
    "goods": {
        "goodsId": 123,
        "goodsName": "test_goods"
    },
    "orderItem": [{
        "orderItemId": 1324,
        "orderItemNo": "34535345"
    }]
}

/json/sample/spec.json

表达式json文件

[{
    "operation": "shift",
    "spec": {
        "orderId": "data.order_id",
        "orderNo": "data.order_no",
        "orderItem": {
            "*": {
                "orderItemId": "data.order_item.[#2].order_item_id",
                "orderItemNo": "data.order_item.[#2].order_item_no"
            }
        }
    }
},
    {
        "operation": "default",
        "spec": {
            "Range": 5,
            "data": {
                "default": 12345
            }
        }
    }
]

输出结果:

{
  "data" : {
    "order_id" : 1212,
    "order_no" : "202223434343",
    "order_item" : [ {
      "order_item_id" : 1324,
      "order_item_no" : "34535345"
    } ],
    "default" : 12345
  },
  "Range" : 5
}

jolt的不同模式和用法

shift       : 将输入json复制到输出json
default     : 为输出的json树中增加默认值
remove      : 从json树中去除指定的key
sort        : 按字母顺序排序映射键值
cardinality : 修正输入数据的基数。urls元素通常是一个List,但是如果只有一个,那么它就是一个字符串
modify-overwrite-beta:总是写
modify-default-beta:当键值对应的值是null时写入
modify-define-beta:当键值不存在时写入
自定义Java类全路径名称:实现Transform或ContextualTransform接口,可选择SpecDriven接口
上面的模式是可以互相结合使用的,下文会详细讲解
以上的说明借鉴了"Panda诚博客" 博客的内容,下面有给出博主的博客地址

上面的前5种类型都只对json的结构进行转换,如果需要对数据进行操作则需要用到modify等相关操作
这里也给大家推荐一下,同样分享jolt的博主 Panda诚博客 传送门.
下面我会给大家详细说明以上不同模式的用法和一些样例。

shift模式的详细例子

shift 模式的作用的将一个input 的json 转成 expected的json,只改变数据结构,不对数据进行操作

简单的格式转换

input 输入:

   {
     "order": {
          "orderItem": {
             "id": 3,
             "num": 5
          }
       }
   }
   

expected 预期输出:

   {
     "orderForm": {
          "orderDetails": {
             "id": 3,
             "num": 5
          }
       }
   }
   

jolt简单的表达式如下:

[
 {
   "operation": "shift",
   "spec": {
     "order": {
       "orderItem": {
         "id": "orderForm.orderDetails.id", // 将id 为3的值复制到 "orderForm.orderDetails.id"的路径上
         "num": "orderForm.orderDetails.num" // 将num为 5的值复制到"orderForm.orderDetails.num"
       }
     }
   }
 }
]
shift模式中‘&’和‘*'的简单使用

'*'的用法和正则表达式中的类似,指的是模糊匹配,下面我们用具体的例子说明
input 输入:

{
  "rating": {
    "primary": {
      "value": 3
    },
    "quality": {
      "value": 3
    }
  }
}

expected 预期输出:

{
  "SecondaryRatings" : {
    "data_primary" : {
      "val" : 3
    },
    "data_quality" : {
      "val" : 3
    }
  }
}

jolt 表达式如下:

[
  {
    "operation": "shift",
    "spec": {
      "rating": {
        "*": { //这里的‘*’匹配的是 input 中的 primary 和 quality
          "value": "SecondaryRatings.data_&1.val" // &1匹配的就是 primary 或 quality
        }
      }
    }
  }
]

这里我们来讲解一下‘&’的用法比如上文的表达式,&1 指的意思就是“value”上一级的key,那“value”上一级的key
就是‘*’,又因为“*”匹配的是primary 和 quality,所以 &1取到的就是(primary 或 quality),同理 &2 取到的就是key “rating”

下面我们再用更多具体的例子,让大家更深入了解“&”的用法
下面为大家讲解如何利用将input 一个值赋值给两个key
input 输入:

{
  "rating_primary_value": 3
}

expected 预期输出:

{
  "key_primary" : 3,
  "key_value" : 3
}

jolt 表达式,这里给大家演示两种方式

//方式1: 
[
  {
    "operation": "shift",
    "spec": {
    //这里数组的意思是将 rating_primary_value 的值拷贝到数组元素的key中
      "rating_primary_value": ["key_primary", "key_value"] 
    }
  }
]

//方式2:
[
  {
    "operation": "shift",
    "spec": { 
    // 第一个“*”号匹配的是"primary",第二的“*”匹配的是"value"  
    //&(0,1)指的是第一个“*”号匹配的值,&(0,2)指的是第二个星号匹配的值
      "rating_*_*": ["key_&(0,1)", "key_&(0,2)"]
    }
  }
]

//上面这个例子 &0 和&(0,0)的效果是等价的匹配到的都是 “rating_primary_value” ,&(0,1)指的就是在 "rating_*_*" 中一个*号匹配的值"primary", 以此类推 
// &1 和 &(1,0)匹配到的是 “root”,这个后面我们的源码中会讲解

shift模式中数组的转换和 ‘#’的使用

'#'的作用通常是用来转换数组的,下面我们用具体的例子讲解
input 输入:

{
    "orderId": 1212,
    "orderNo": "202223434343",
    "orderItem": [
        {
            "orderItemId": 1,
            "orderItemNo": "2022xxxxxx01",
            "goods": [
                {
                    "goodsId": 1,
                    "goodsNum": 5
                },
                {
                    "goodsId": 2,
                    "goodsNum": 6
                }
            ]
        },
        {
            "orderItemId": 2,
            "orderItemNo": "2022xxxxxx02",
            "goods": [
                {
                    "goodsId": 3,
                    "goodsNum": 6
                },
                {
                    "goodsId": 4,
                    "goodsNum": 7
                }
            ]
        }
    ]
}

shift :

[{
	"operation": "shift",
	"spec": {
		"orderId": "o_id",
		"orderNo": "o_no",
		"orderItem": {
			"*": { // '*' 匹配的是orderItem数组的下标
				"orderItemId": "o_item.[#2].o_item_id", // #2代表的是从orderItemId往上数的第二个key,也就是'orderItem',这就代表着 o_item数组对标 输入的 orderItem
				"orderItemNo": "o_item.[#2].o_item_no",
				"goods": {
					"*": {
						"goodsId": "o_item.[#4].o_goods.[#2].g_id", // 这里类似 [#4] 往上数4就是'orderItem',[#2]就是 'goods'
						"goodsNum": "o_item.[#4].o_goods.[#2].g_num"
					}
				}
			}
		}
	}
}]

输出:

{
    "o_id": 1212,
    "o_no": "202223434343",
    "o_item": [
        {
            "o_item_id": 1,
            "o_item_no": "2022xxxxxx01",
            "o_goods": [
                {
                    "g_id": 1,
                    "g_num": 5
                },
                {
                    "g_id": 2,
                    "g_num": 6
                }
            ]
        },
        {
            "o_item_id": 2,
            "o_item_no": "2022xxxxxx02",
            "o_goods": [
                {
                    "g_id": 3,
                    "g_num": 6
                },
                {
                    "g_id": 4,
                    "g_num": 7
                }
            ]
        }
    ]
}

如果输入的json 是一个数组要怎么转换呢,请看下面的例子
input 输入:

[
    {
        "orderItemId": 1,
        "orderItemNo": "2022xxxxxx01"
    },
    {
        "orderItemId": 2,
        "orderItemNo": "2022xxxxxx02"
    }
]

预期输出:

[ {
  "orderId" : 1,
  "orderNo" : "2022xxxxxx01"
}, {
  "orderId" : 2,
  "orderNo" : "2022xxxxxx02"
} ]

spec 表达式:

[
  {
    "operation": "shift",
    "spec": {
      "*": {
        "orderItemId": "[#2].orderId",
        "orderItemNo": "[#2].orderNo"
      }
    }
  }
]

其实除了使用‘#’进行数组的转换,还可以使用“&”来实现,比如上文的转换,也可以使用如下表达式
spec 表达式:

[
  {
    "operation": "shift",
    "spec": {
      "*": {
        "orderItemId": "[&1].orderId",
        "orderItemNo": "[&1].orderNo"
      }
    }
  }
]

shift 模式也支持取出指定下标的元素

{
  "order": [
    {
      "orderItemId": 1,
      "orderItemNo": "2022xxxxxx01"
    },
    {
      "orderItemId": 2,
      "orderItemNo": "2022xxxxxx02"
    }
  ]
}

取出下标为0的元素 spec:

[
  {
    "operation": "shift",
    "spec": {
      "order": {
        "0": "order"
      }
    }
  }
]

输出结果:

{
  "order" : {
    "orderItemId" : 1,
    "orderItemNo" : "2022xxxxxx01"
  }
}

‘&’转换数组和‘#’的区别在于[]里面的数值,‘&’ 比‘#’小1,
[&]对应的是下标,如上文 * 匹配的是下标 0或 1,[&1]只的就是对应的下标0或1
[#]要对应的是上层的key,如上文,[#2]对应的是key ‘root’,有小伙伴就会产生疑问这个‘root’是哪来的,input里面没有呀,别着急后续我们会在源码篇详细讲解

上面将的都是‘#’在LHS的用,下面我们将一下‘#’在 RHS变的用法,‘#’在RHS可以给输出key赋值指定字符串

{
  "rating": "555",
  "primary": "1234"
}

spec:

[
  {
    "operation": "shift",
    "spec": {
      "rating": "rating",
      "primary": "primary",
      "#666": "value" //给value 赋值 “666”
    }
  }
]

输出结果:

{
  "value" : "666",
  "rating" : "555",
  "primary" : "1234"
}

基于上面的用法比较常用的转换就是枚举值的转换
假设我们这这样一个例子,输出一个sex 字段,1代表男,2代表女,我们需要把这个字段转换成SexEnum枚举类

package com.example.oxy.enums;
import lombok.Getter;

/**
 * 性别枚举类
 * @author oxy
 */
public enum SexEnum {
    MAN("男", "man"),
    WOMAN("女", "woman");

    @Getter
    private String desc;

    @Getter
    private String code;

    SexEnum(String desc, String code) {
        this.desc = desc;
        this.code = code;
    }
}

input 输入:

{
  "name": "张三",
  "sex": 1
}

shift:

[
  {
    "operation": "shift",
    "spec": {
      "name": "name",
      "sex": {
        "1": { //如果sex =1 ,将其转成男性枚举值
          "#男": "sex.desc",
          "#man": "sex.code"
        },
        "2": { //如果sex =2 ,将其转成女性枚举值
          "#女": "sex.desc",
          "#woman": "sex.code"
        }
      }
    }
  }
]

{
  "name" : "张三",
  "sex" : {
    "desc" : "男",
    "code" : "man"
  }
}
shift模式中 ‘$’的使用

'$'的作用是将input中的key当做值,映射给输出的json key中,请看下面的例子
input 输入:

{
  "rating": {
    "primary": {
      "value": 3
    },
    "quality": {
      "value": 3
    }
  }
}

spec:

[
  {
    "operation": "shift",
    "spec": {
      "rating": {
        "primary": {
          "value": "Rating",
          "max": "RatingRange"
        },
        "*": { //"*"匹配的是 quality
          "$": "SecondaryRatings.Id" //"$"的意思是将“*”匹配的key 当做值赋值给 SecondaryRatings.Id
        }
      }
    }
  }
]

输出:

{
  "Rating" : 3,
  "SecondaryRatings" : {
    "Id" : "quality"
  }
}
shift模式中 ‘@’的使用

‘@’ LHS、RHS都有效,意义一样,可以取到数据树中指定的值,单独写@时是等价于@0的,下面我们有具体的例子来讲解
input 输入:

{
  "rating": {
    "primary": 111,
    "quality": 222
  },
  "xxx": 4444
}

spec:

[
  {
    "operation": "shift",
    "spec": {
      "rating": {
        "@": "yyy"  //将@等价于@0,代表的是将 rating 的值赋值给yyy
      }
    }
  }
]

输出:

{
  "yyy" : {
    "primary" : 111,
    "quality" : 222
  }
}

input 输入:

{
  "rating": {
    "primary": 111,
    "quality": 222
  },
  "xxx": 4444
}

spec:

[
  {
    "operation": "shift",
    "spec": {
      "rating": {
        "@primary": "yyy", //将@primary等价于@(0,primary),代表的是将 primary 的值赋值给yyy
        "@quality": "aaa", //将@primary等价于@(0,quality),代表的是将 quality 的值赋值给aaa
        "@(1,xxx)": "bbb", //@(1,xxx) 的1代表和rating同一个等级的xxx 的值赋值给 bbb
        "primary": {
          "@(2,xxx)": "ccc" //@(2,xxx)的2是'primary'指往上数2个等级的也就是和rating同一等级的xxx的值赋值给ccc
        }
      }
    }
  }
]

输出:

{
  "yyy" : 111,
  "aaa" : 222,
  "bbb" : 4444,
  "ccc" : 4444
}

'@'在RHS的使用例子

input 输入:

{
  "rating": {
    "primary": "orderKey",
    "quality": "order"
  }
}

spec:

[
  {
    "operation": "shift",
    "spec": {
      "rating": {
        "@primary": "@quality" //将rating.primary的值赋值给 order,order是rating.quality的值
      }
    }
  }
]

输出:

{
  "order" : "orderKey"
}

default 模式的详细例子

default 的作用是给json赋默认值,如果对应的key不存在或值为null时,给其赋上默认值

简单的赋默认值

input 输入:

{
  "rating": {
    "primary": {
      "value": 3
    },
    "quality": {
      "value": 3
    }
  }
}
   

expected 预期输出:

{
"rating" : {
 "primary" : {
   "value" : 3,
   "Range" : 5
 },
 "quality" : {
   "value" : 3,
   "Range" : 5
 }
},
"Range" : 5
}

jolt简单的表达式如下:

[
 {
   "operation": "default",
   "spec": {
     "Range": 5,
     "rating": {
       "*": {//这是的星号匹配的是key "primary" 和 "quality"
         // 给rating.primary.Range、rating.quality.Range赋默认值5
         "Range": 5
       }
     }
   }
 }
]

default 默认是只能给不存在的key或key 为null的字段 赋默认值,如果对应的key已存在具体值default的配置则不会起效果

例子:  
input 输入:  
{
   "default": null
 } 
jolt 表达式:
 [
   {
     "operation": "default",
     "spec": {
       "Range": 5,
       "default": 6
     }
   }
 ]    
 expected输出结果:
{
  "default" : 6,
  "Range" : 5
}

input  如果输入的结果是:
{
   "default": 3
 }
 expected输出结果:
 {
   "default" : 3,
   "Range" : 5
 }

remove 模式的详细例子

remove 的作用是将json中不需要的key进行删除

简单的remove例子

input 输入:

{
  "rating": {
    "primary": {
      "value": 3,
      "id": 23
    },
    "quality": {
      "value": 3,
      "id": 24
    }
  }
}
   

spec :

[
  {
    "operation": "remove",
    "spec": {
      "rating": {
        "primary": "", //删除 rating.primary
        "quality": {
          "id": "" //删除 rating.quality.id
        }
      }
    }
  }
]

expected 输出:

{
"rating" : {
 "quality" : {
   "value" : 3
 }
}
}

cardinality 模式的详细例子

简单的cardinality例子

cardinality模式的作用是可以将单个数据包装成数组,或者取出数组中第一个元素
‘ONE’:如果输入值是一个列表,则获取该列表中的第一个元素,并将其设置为该元素的数据,不支持其他类型
‘MANY’:如果输入不是列表,则创建一个列表并将第一个元素设置为输入值。如果输入是"null",使它成为一个空列表。如果输入是一个列表,不支持。

input 输入:

{
    "rating": {
        "primary": [
            {
                "value": 3,
                "id": 23
            },
            {
                "value": 3,
                "id": 23
            }
        ],
        "quality": {
            "value": 5,
            "id": 25
        }
    }
}
   

spec :

[
  {
    "operation": "cardinality",
    "spec": {
      "rating": {
        "primary": "ONE", //取出 primary 中的一个元素
        "quality": "MANY" //将 quality 转换成数组
      }
    }
    }
]

expected 输出:

{
 "rating": {
     "primary": {
         "value": 3,
         "id": 23
     },
     "quality": [
         {
             "value": 5,
             "id": 25
         }
     ]
 }
}

modify 模式的详细例子

modify相关案例讲解

modify又分成如下模式:
modify-overwrite-beta: 模式是对指定的key的数据进行操作,无法key是否存在或已存在值,始终会对其进行操作
default modify-default-beta :当键值对应的值是null时写入
define modify-define-beta :当键值不存在时写入
modify 模式包含如下函数:

    private static final Map<String, Function> STOCK_FUNCTIONS = new HashMap<>(  );

    static {
        STOCK_FUNCTIONS.put( "toLower", new Strings.toLowerCase() );
        STOCK_FUNCTIONS.put( "toUpper", new Strings.toUpperCase() );
        STOCK_FUNCTIONS.put( "concat", new Strings.concat() );
        STOCK_FUNCTIONS.put( "join", new Strings.join() );
        STOCK_FUNCTIONS.put( "split", new Strings.split() );
        STOCK_FUNCTIONS.put( "substring", new Strings.substring() );
        STOCK_FUNCTIONS.put( "trim", new Strings.trim() );
        STOCK_FUNCTIONS.put( "leftPad", new Strings.leftPad() );
        STOCK_FUNCTIONS.put( "rightPad", new Strings.rightPad() );

        STOCK_FUNCTIONS.put( "min", new Math.min() );
        STOCK_FUNCTIONS.put( "max", new Math.max() );
        STOCK_FUNCTIONS.put( "abs", new Math.abs() );
        STOCK_FUNCTIONS.put( "avg", new Math.avg() );
        STOCK_FUNCTIONS.put( "intSum", new Math.intSum() );
        STOCK_FUNCTIONS.put( "doubleSum", new Math.doubleSum() );
        STOCK_FUNCTIONS.put( "longSum", new Math.longSum() );
        STOCK_FUNCTIONS.put( "intSubtract", new Math.intSubtract() );
        STOCK_FUNCTIONS.put( "doubleSubtract", new Math.doubleSubtract() );
        STOCK_FUNCTIONS.put( "longSubtract", new Math.longSubtract() );
        STOCK_FUNCTIONS.put( "divide", new Math.divide() );
        STOCK_FUNCTIONS.put( "divideAndRound", new Math.divideAndRound() );


        STOCK_FUNCTIONS.put( "toInteger", new Objects.toInteger() );
        STOCK_FUNCTIONS.put( "toDouble", new Objects.toDouble() );
        STOCK_FUNCTIONS.put( "toLong", new Objects.toLong() );
        STOCK_FUNCTIONS.put( "toBoolean", new Objects.toBoolean() );
        STOCK_FUNCTIONS.put( "toString", new Objects.toString() );
        STOCK_FUNCTIONS.put( "size", new Objects.size() );
        STOCK_FUNCTIONS.put( "toJsonString", new Objects.toJsonString() );

        STOCK_FUNCTIONS.put( "squashNulls", new Objects.squashNulls() );
        STOCK_FUNCTIONS.put( "recursivelySquashNulls", new Objects.recursivelySquashNulls() );
        STOCK_FUNCTIONS.put( "squashDuplicates", new Objects.squashDuplicates() );

        STOCK_FUNCTIONS.put( "noop", Function.noop );
        STOCK_FUNCTIONS.put( "isPresent", Function.isPresent );
        STOCK_FUNCTIONS.put( "notNull", Function.notNull );
        STOCK_FUNCTIONS.put( "isNull", Function.isNull );

        STOCK_FUNCTIONS.put( "firstElement", new Lists.firstElement() );
        STOCK_FUNCTIONS.put( "lastElement", new Lists.lastElement() );
        STOCK_FUNCTIONS.put( "elementAt", new Lists.elementAt() );
        STOCK_FUNCTIONS.put( "toList", new Lists.toList() );
        STOCK_FUNCTIONS.put( "sort", new Lists.sort() );
    }

其对应函数的功能和java同名函数一样
toLower :将字符转成小写
toUpper : 将字符转成大写
concat :合并字符串
下面就不一一说明了,详情说明可以访问开源项目查看

modify-overwrite-beta相关案例讲解

字符串相关处理

input 输入:

{
  "rating": {
    "primary": {
      "value": 3,
      "value1": "ABC",
      "value2": "dnf"
    },
    "quality": {
      "value": 3
    }
  }
}

spec :

[
  {
    "operation": "modify-overwrite-beta",
    "spec": {
      "rating": {
        "primary": {
          "value": "=toString", //将 value转成字符串
          "value1": "=toLower", //将value1的字符变成小写
          "value2": "=toUpper", //将value2的字符变成大写
          "value3": "=concat(a,b,c,d,e,c,g)", //将括号里的数值拼成字符串
          "value4": "=join('_',5,4,5,6,7,8,9,90,0)", // 以‘—’将后面的元素连接在一起
          "value5": "=split('_','order_item_info')", //以‘_’分割字符串
          "value6": "=substring('abcdefg',3,3)", //截取‘abcdefg’的子串
          "value7": "=trim", // 去除 ‘ yy ’ 前后空格
          "value8": "=leftPad('abc',5,c)", // 5 - 'abc'.length()等于2,所在在左边增加两个c
          "value9": "=rightPad('abc',5,d)" // 5 - 'abc'.length()等于2,所在在右边增加两个d
        },
        "quality": {
          "value1": "=min(1,3,4,6)", // 从 1,3,4,6中选最小值赋值给value1
          "value2": "=max(1,3,4,6)" // 从 1,3,4,6中选最大值赋值给value2
        }
      }
    }
  }
]

expected 输出:

{
"rating" : {
 "primary" : {
   "value" : "3",
   "value1" : "abc",
   "value2" : "DNF",
   "value7" : "yy",
   "value3" : "abcdecg",
   "value4" : "5_4_5_6_7_8_9_90_0",
   "value5" : [ "order", "item", "info" ],
   "value8" : "ccabc",
   "value9" : "abcdd"
 },
 "quality" : {
   "value" : 3,
   "value1" : 1,
   "value2" : 6
 }
}
}
数学运算

input 输入:

{
  "rating": {
    "primary": {
      "value": 3
    },
    "quality": {
      "value": 3
    }
  }
}

spec :

[
  {
    "operation": "modify-overwrite-beta",
    "spec": {
      "rating": {
        "quality": {
          "value1": "=min(1,3,4,6)", // 从 1,3,4,6中选最小值赋值给value1
          "value2": "=max(1,3,4,6)", // 从 1,3,4,6中选最大值赋值给value2
          "value3": "=abs(-100)", //取一个数据的绝对值
          "value4": "=avg(1,2,3)", // 取 1,2,3 的平均值
          "value5": "=intSum(1,2,3)", // int求和
          "value6": "=doubleSum(1.0,2.0,3.0)", // double求和
          "value7": "=longSum(10000,20000,30000)", //long求和
          "value8": "=intSubtract(6,2)", //整数减法 6-2
          "value9": "=doubleSubtract(6.0,2.2)", //浮点数减法6.0 - 2.2
          "value10": "=divide(10,2)", //除法 10/2
          "value11": "=divideAndRound(2,30,7)" //除法 30/7四舍五入,第一个2参数指的是保留几位小数
        }
      }
    }
  }
]

expected 输出:

{
"rating" : {
 "primary" : {
   "value" : 3
 },
 "quality" : {
   "value" : 3,
   "value1" : 1,
   "value2" : 6,
   "value3" : 100,
   "value4" : 2.0,
   "value5" : 6,
   "value6" : 6.0,
   "value7" : 60000,
   "value8" : 4,
   "value9" : 3.8,
   "value10" : 5.0,
   "value11" : 4.29
 }
}
}

类型转换

input 输入:

{
  "rating": {
    "primary": {
      "value1": "3",
      "value2": 2,
      "value3": "33",
      "value4": "false",
      "value5": 1999,
      "value6": "123456789"
    }
  }
}

spec :

[
  {
    "operation": "modify-overwrite-beta",
    "spec": {
      "rating": {
        "primary": {
          "value1": "=toInteger", // 转换成int类型
          "value2": "=toDouble", // 转换成Double类型
          "value3": "=toLong", //转换成long类型
          "value4": "=toBoolean", //转换成Boolean类型
          "value5": "=toString", // 转换成String类型
          "value6": "=size", // 求字符串长度
          "value7": "=size(1,2,3,4,5,6,7,8)" //求数组元素个数
        }
      }
    }
  }
]

expected 输出:

{
"rating" : {
 "primary" : {
   "value1" : 3,
   "value2" : 2.0,
   "value3" : 33,
   "value4" : false,
   "value5" : "1999",
   "value6" : 9,
   "value7" : 8
 }
}
}

数组的操作

input 输入:

{
  "rating": {
    "primary": {
      "value0":[6,5,4,3,2,1],
      "value1": [ "a", null, 1, null, "b" ],
      "value2": [ "a", null, { "x": "X", "y": null, "zList" : [ "z1", null, "z3" ] }, null, "b"  ],
      "value3": [ "abc", "abc", "xyz", "cde", "bcd" ],
      "value4": [ "abc", "abc", "xyz", "cde", "bcd" ],
      "value5": [ "abc", "abc", "xyz", "cde", "bcd" ],
      "value6": [ "abc", "abc", "xyz", "cde", "bcd" ]
      
    }
  }
}

spec :

[
  {
    "operation": "modify-overwrite-beta",
    "spec": {
      "rating": {
        "primary": {
          "value1": "=squashNulls", // 去除空值
          "value2": "=recursivelySquashNulls", // 递归去除空值
          "value3": "=squashDuplicates", //去除重复值
          "value4": "=firstElement", //取数组第一个值
          "value5": "=lastElement", // 取数组最后一个值
          "value6": "=elementAt(2,@(1,value0))", // 取value0数组下标为2的值
          "value7": "=toList(10)", //将元素转换数组
          "value8": "=sort(@(1,value0))" //将value0升序排序
        }
      }
    }
  }
]

expected 输出:

{
"rating" : {
 "primary" : {
   "value0" : [ 6, 5, 4, 3, 2, 1 ],
   "value1" : [ "a", 1, "b" ],
   "value2" : [ "a",  {"x" : "X","zList" : [ "z1", "z3" ] }, "b" ],
   "value3" : [  "abc", "xyz", "cde", "bcd" ],
   "value4" : "abc",
   "value5" : "bcd",
   "value6" : 4,
   "value7" : [ 10 ],
   "value8" : [ 1, 2, 3, 4, 5, 6 ]
 }
}
}

不同模式结合使用的案例

不同模式结合使用的相关案例讲解

jolt的表达式是一个列表,所以我们在使用的时候可以结合多种模式一起使用

input 输入:

{
  "rating": {
    "primary": {
      "value": 3
    },
    "quality": {
      "value": 3
    }
  }
}
   

spec:

[
 {
   "operation": "shift",
   "spec": {
     "rating": {
       "primary": {
         // simple match.  Put the value '4' in the output under the "Rating" field
         "value": "Rating",
         "max": "RatingRange"
       },
       // match any children of "rating"
       // Shiftr has a precendence order when matching, so the "*" will match "last".
       // In this case anything that isn't "primary".
       "*": {
         // &1 means, go up one level and grab that value and substitute it in
         //  in this example &1 = "quality"
         "max":   "SecondaryRatings.&1.Range",
         "value": "SecondaryRatings.&1.Value",
         //
         // We want "quality" to be a value field in the output under
         //  "SecondaryRatings.quality.Id", but "quality" is an input key not an input value.
         // The "$" operator means use the input key, instead of the input value as ouput
         "$": "SecondaryRatings.&1.Id"
       }
     }
   }
 },
 {
   "operation": "default",
   "spec": {
     "Range": 5,
     "SecondaryRatings": {
       "*": {
         // Defaut all "SecondaryRatings" to have a Range of 5
         "Range": 5
       }
     }
   }
 }
]

expected 输出:

{
"Rating" : 3,
"SecondaryRatings" : {
 "quality" : {
   "Id" : "quality",
   "Value" : 3,
   "Range" : 5
 }
},
"Range" : 5
}

需要查看更多详细的例子可以访问开源项目查看
github jolt教程 开源项目 jolt-universe.
gitCode jolt 教程 开源项目 jolt-universe.
gitee 码云 jot教程 开源项目 jolt-universe.

知秋君
上一篇 2024-08-21 11:02
下一篇 2024-08-21 10:36

相关推荐