工具 | 版本 |
---|---|
mule-standalone | 3.9.0 |
Anypoint-Studio | 6.4.0 |
遍历操作是编程中经常使用到的操作,在DataWeave Language中,遍历需要使用到的是操作符是Map
。同时也借Map操作符来进一步了解DataWeave Language的使用规律,毕竟操作符语法之间并不存在太大差异,彻底掌握一个操作符的运用后,那么其他操作符使用起来相信也不会太难了。
Returns an array that is the result of applying a transformation function (lambda) to each of the elements. The lambda is invoked with two parameters: index and the value. If these parameters are not named, the index is defined by default as $$ and the value as $.
首先这段话有一个奇怪的名词,那就是lambda(即数学里面的λ),经过网上搜索,Mule使用了lambda表达式
。如果想了解lambda表达式,或许可以看一下这篇我找的博文,从java角度解释lambda 点这里。
官网说,这个Map操作符返回一个array
,这个array是经过function(λ)处理后的结果。λ有两个参数,一个是value,一个是index。如果这两个参数没有被命名,value使用$
代替,index使用$$
代替。
官网给出了一个直观的例子:
%dw 1.0
%output application/json
---
users: ["john", "peter", "matt"] map ((firstName, position) -> position ++ ":" ++ upper firstName)
其中map ((firstName, position) -> position ++ ":" ++ upper firstName)
就是一个lambda表达式,请注意第一个参数是value
,第二个参数是index
。正如上面所说,参数没有命名才使用$符号来代替。而表达式中->
是lambda的语法。不必太纠结于lambda的语法,重点关注点是->后的内容,因为这里才是输出的结构定义。处理的输入是[“john”, “peter”, “matt”],然后通过map操作符
会使得每一个数组元素都按照你所设置的格式转变。
而需要注意,++
符号不是自增的意思,而是DataWeave里面的字符串拼接符号。如果你使用一个+则会报错。upper也是关键字,作用使value值大写。
最后的输出结果如下:
{
"users": [
"0:JOHN",
"1:PETER",
"2:MATT"
]
}
上面官网给出的例子结构上简单,因此下面准备了一个XML输入,相对结构复杂点。将其按照要求转为所需JSON格式。
XML输入
<?xml version='1.0' encoding='UTF-8'?>
<orders>
<order>
<product>
<price>5</price>
<model>MuleSoft Connect 2016</model>
</product>
<item_amount>3</item_amount>
<payment>
<payment-type>credit-card</payment-type>
<currency>USD</currency>
<installments>1</installments>
</payment>
<buyer>
<email>mike@hotmail.com</email>
<name>Michael</name>
<address>Koala Boulevard 314</address>
<city>San Diego</city>
<state>CA</state>
<postCode>1345</postCode>
<nationality>USA</nationality>
</buyer>
<shop>main branch</shop>
<salesperson>Mathew Chow</salesperson>
</order>
<order>
<product>
<price>10086</price>
<model>MuleSoft Connect 2018</model>
</product>
<item_amount>2333</item_amount>
<payment>
<payment-type>credit-card</payment-type>
<currency>USD</currency>
<installments>1</installments>
</payment>
<buyer>
<email>cgydawn@hotmail.com</email>
<name>cgydawn</name>
<address>beijing,china 314</address>
<city>San Diego</city>
<state>AC</state>
<postCode>123456</postCode>
<nationality>USA</nationality>
</buyer>
<shop>meiyijia shop</shop>
<salesperson>zhangsan</salesperson>
</order>
</orders>
XML里面根元素是orders,里面包含两个订单信息。每个订单信息里面又包含产品信息,产品购买数量,支付信息,买家信息,购买地点,销售员名信息。这些信息里面部分还有子信息。
获取该XML输入中买家的信息
达到目标的DataWeave语句
%dw 1.0
%output application/json
---
userInfo : payload.orders map {
email : $.buyer.email,
name : $.buyer.name,
address : $.buyer.address,
city : $.buyer.city,
state : $.buyer.state,
postCode : $.buyer.postCode,
nationality : $.buyer.nationality
}
JSON输出
需要注意
:一开始的时候,按照遍历的想法,我几乎想也不想地直接写出这样的语句
%dw 1.0
%output application/json
---
userInfo : payload map {
email : $.order.buyer.email
}
获取不完全正确
这样的语句并没有报错,同时还有输出,但是仅仅只输出了第一个订单的电子邮箱信息,然而目标输入是有两个订单信息的。那为什么没有遍历两次而只有一次?对比就知道实际是payload
和payload.orders
的差别。如果你使用前者,按照我的理解,map拿去遍历的长度相当于orders数量,即1。但是使用后者,map拿去遍历的长度相当于order长度,即2。同时也应该留意到,map
前的格式,会影响到你后续使用的层级关系。
使用payload
给map操作符处理,则map直接处理的是payload(),$
从其直接子元素order开始执行。
使用payload.orders
给map操作符处理,则map直接处理的是payload.orders(),$
从其直接子元素product,item_amount,payment,buyer之一开始。
因为需要获取的是买家信息,因此大括号内用的是$.buyer.xxx
形式,当然使用$.product.model
也是可以的,但那就不是获取买家信息了。
Using Map on an Object(对一个Object进行Map操作)
Map操作符除了对数组类的数据进行处理外,官网还提示它可以对对象进行处理。官网例子将XML输入转为JSON输出,并且将不同价位的美元价格按照给出的固定汇率转为新的价格。
XML输入
<?xml version='1.0' encoding='UTF-8'?>
<prices>
<basic>9.99</basic>
<premium>53</premium>
<vip>398.99</vip>
</prices>
正确DataWeave语句一
%dw 1.0
%output application/json
%var conversionRate=13.45
---
priceList: payload.prices map (
'$$':{
dollars: $,
localCurrency: $ * conversionRate
}
)
正确DataWeave语句二
%dw 1.0
%output application/json
%var conversionRate=13.45
---
priceList: payload.prices map ((money, position) ->
'$position':{
dollars: money,
localCurrency: money * conversionRate
}
)
需要注意的是,语句二的语法形式上要求,如果index已经有了命名,则使用index时,需要在命名前加上$
,然后用单引号包括。即'$position'
等价于 $$
。 同时,index参数是可选的,因此下面形式也是正确的,只是不能输出索引信息。
正确DataWeave语句三
%dw 1.0
%output application/json
%var conversionRate=13.45
---
priceList: payload.prices map ((money) ->
{
dollars: money,
localCurrency: money * conversionRate
}
)
参考资料
官网Map操作符说明