Camel中的JSLT组件是用来处理Json消息的一个组件。当执行Json到Json的数据转换或者查询时,这个组件是能够帮你完成的。<br />Maven用户将需要为其组件添加以下依赖项pom.xml
:
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-jslt-starter</artifactId>
<version>x.x.x</version>
<!-- use the same version as your Camel core version -->
</dependency>
URI格式<br />其中specName是要调用的规范的类路径本地URI;或远程规范的完整URL(例如:file:Json2Json/test.json)。<br />你可以在路径添加以下参数:
jslt:specName?name=value
名称 | 描述 | 默认值 | 类型 |
---|---|---|---|
allowTemplateFromHeader | 是否允许使用标题中的资源模板(默认为false)。启用此功能可以通过消息头指定动态模板。但是,如果标头来自恶意用户,则可以将其视为潜在的安全漏洞,因此请谨慎使用。 | false | boolean |
lazyStartProducer | 生产者是否应该开启懒加载(在第一个消息上)。通过延迟启动,您可以使用它来允许CamelContext和路由启动,以防生产者在启动过程中否则可能失败并导致路由启动失败。通过延迟启动时间,可以在通过Camel的路由错误处理程序路由消息期间处理启动失败。请注意,当处理第一个消息时,创建并启动生产者可能会花费一些时间,并会延长处理的总处理时间。 | false | boolean |
autowiredEnabled | 是否启用自动装配。通过在注册表中查找是否存在单个匹配类型的实例,将其用于自动自动装配选项(该选项必须标记为自动接线),然后在组件上进行配置。这可用于自动配置JDBC数据源,JMS连接工厂,AWS客户端等。 | true | boolean |
JSLT端点是使用URI语法配置的:
jslt:resourceUri
resourceUri:资源的必需路径。您可以添加以下前缀:classpath,file,http,ref或bean。classpath,file和http使用这些协议加载资源(默认为classpath)。ref将在注册表中查找资源。bean将在bean上调用一个方法用作资源。对于bean,您可以在点后指定方法名称,例如bean:myBean.myMethod。
语法教程:
在JSLT中,您可以编写表达式。该表达式的计算结果为JSON。因此结果可以是对象,数字,字符串,空值等。<br />JSON是JSLT的子集,因此在任何可以编写表达式的地方都可以编写JSON。<br />这是一个有效的JSLT:
{
"user" :
{
"name" : "zhangsan",
"age" : 26
}
}
在这里你可以使用来点表达式访问对象键,.user结果为:
{
"name" : "zhangsan",
"age" : 26
}
也可以链接起来使用,.user.name结果为:
"zhangsan"
数组索引
定义一个数组
{
"foo" :
{
"bar" : [1,2,3,4,5]
}
}
您还可以使用进行数组索引编制[ index ]
,这样.foo.bar[0]
的结果为1
。<br />支持数组切片,因此您可以编写[1 : 3]
结果为[2, 3]
。第一个索引是包含的,最后一个索引是不包含的的。<br />您可以使用负索引来引用从数组末尾开始的元素,这样就[-1]
可以返回数组的最后一个元素5
。这也适用于切片,因此要删除第一个和最后一个元素,请执行 [1 : -1]
。
<a name="jwHXL"></a>
JSON构造
在JSON内部,您可以在可以编写JSON文字的任何地方编写表达式,因此您可以创建一个新的对象,如下所示:
{
"array" : .foo.bar
}
结果为:
{
"array" : [1,2,3,4,5]
}
函数
JSLT具有许多内置函数,例如size
,可以返回对象或数组中的元素数或字符串中的字符数。函数语法是常见的语法,因此我们也可以这样写:
{
"array" : .foo.bar,
"size" : size(.foo.bar)
}
结果为:
{
"array" : [1,2,3,4,5],
"size" : 5
}
更多函数:https://github.com/schibsted/jslt/blob/master/functions.md
<a name="bd4lu"></a>
if表达式
我们也有if
使用语法的测试:
if (<expr>) <expr> else <expr>
if
始终返回一个值,并且不执行其他任何操作。可以省去该else
零件,在这种情况下,条件if
将为null
假。<br />布尔false
,null
空对象和空数组都被认为是false
。这意味着我们可以将转换编写如下:
if (.foo.bar)
{
"array" : [for (.foo.bar) string(.)],
"size" : size(.foo.bar)
}
else
"No array today"
在这种情况下,如果键中没有任何内容(或空数组), .foo.bar
则会获取字符串。如果要区分空数组和根本不区分数组,可以进行显式比较:
if (.foo.bar != null)
{
"array" : [for (.foo.bar) string(.)],
"size" : size(.foo.bar)
}
else
"No array today"
for表达式
该for
表达式使您可以通过对每个数组元素上的表达式求值来获取一个数组并将其转换为新数组。语法是
[for (<expr>)
<expr>]
圆括号内的第一个表达式求值成一个数组,我们对其进行循环。对于其中的每个元素,将评估第二个表达式 (.
现在引用当前数组元素)。<br />因此,如果我们想要一个字符串数组,我们可以说:
{
"array" : [for (.foo.bar) string(.)],
"size" : size(.foo.bar)
}
结果为:
{
"array" : ["1","2","3","4","5"],
"size" : 5
}
您也可以在中绑定变量for
。下面的示例产生与第一个示例相同的输出。
{
"array" : [for (.foo.bar)
let s = string(.)
$s],
"size" : size(.foo.bar)
}
for表达式还支持if
在末尾使用表达式对数组进行过滤。这样我们可以写:
let filtered = [for (.foo.bar) string(.) if (. > 3)]
{
"array" : $filtered,
"size" : size($filtered)
}
现在的结果为:
{
"array" : ["4","5"],
"size" : 2
}
表达式对象
也可以使用for
表达式来产生对象。和以前一样,我们分别处理输入数组中的每个元素,但是在这种情况下,我们在对象中为数组中的每个元素创建了一个键。评估键和值时,.
引用当前数组元素。<br />我们可以遍历一直在处理的数组,然后将数组变成一个对象,如下所示:
{for (.foo.bar) string(.) : .}
结果为:
{
"1" : 1,
"2" : 2,
"3" : 3,
"4" : 4,
"5" : 5
}
假设我们要处理一个对象,并将其"custom"
作为前缀添加到每个现有键中。假设我们的输入是:
{
"foo" : 1,
"bar" : 2
}
我们可以使用以下方法处理此问题:
{for (.) "custom_" + .key : .value}
结果为:
{
"custom_foo" : 1,
"custom_bar" : 2
}
运算符
支持通常的运算符。对于算术就可以使用+
, -
,*
,和/
预期。<br />+
也适用于字符串,数组和对象。对于对象,如果两侧都出现相同的键,则左侧的值将“获胜”。<br />还支持通常的比较运算符,因此您可以使用以下命令处理1-5数组
[for (.foo.bar) . > 2]
并得到:
[false, false, true, true, true]
您还可以将布尔值与and
和组合or
。not
是一个功能。因此,您可以将布尔表达式编写为:
.foo.bar > 2 and not(contains(.baz, ["george", "harry"]))
等等。。。
使用camel中的对象
变量名 | 变量说明 |
---|---|
headers | camel message header |
variables | The variables |
exchange.properties | The Exchange properties as a json object. exchange is the name of the variable and properties is the path to the exchange properties. Available if allowContextMapAll option is true. |
上述camel中的变量可以在type中进行转换和使用, 例如header中的type,以及exchange property中的数据都可以直接访问
{
"type": $headers.type,
"instance": $exchange.properties.instance
}
SAMPLES
创建.json文件,定义转换的格式。
实战案例
前端发送来的Json:
{
"signIn" : {
"appId" : "xxxx",
"workNumber" : "xxx",
"gid" : 1,
"type" : 0,
"deviceNumber" : "xxx"
}
}
被调方需要的Json:
{
"req":"xxx",
"agentid":"xxx",
"thisdn":"xxx",
"phone":"xxx",
"tenantid":"xxx",
"token":"xxx",
"code":"xxx"
}
编写.json
文件。
{
"req": "login",
"agentid": .signIn.workNumber,
"phone": .signIn.deviceNumber,
}
通过JSTL组件:
<to uri="jslt:classpath\response.json?contentCache=true"/>
转换后的结果:
{
"req":"xxxx",
"agentid":"xxxx",
"phone":"xxxx"
}
然后再向被调方发送请求。