[Update] 2017-11-08 原本文章的 mapping 方式再依些特別狀況會出錯,在文章最下面加入了最新的 mapping 方式
最近需要在 API Gateway 上面作 request 和 response 的參數調整
這裡紀錄一下一些基本的使用語法
官方網站也有提供使用方式還有一些例子
或是可以直接到 Apache Velocity Template Language
if else
1 | { |
如果參數是 cool 的話,顯示出來是1
2
3{
"variable": "cool"
}
type
以上一個 case 來說,把 variable 改成是 11
2
3{
"variable": "$variable"
}
這樣顯示出來會是1
2
3{
"variable": "1"
}
但是如果改成這種格式1
2
3{
"variable": $variable
}
這樣顯示出來會是1
2
3{
"variable": 1
}
這邊要注意的是,如果格式是以下這樣,然後參數是 “test”1
2
3{
"variable": $variable
}
這樣顯示出來會是1
2
3
4{
// 這會直接讓 API Gateway mapping template 直接爆炸
"variable": test
}
key
如果把 $variable 設成 “test”,並用以下的 template1
2
3{
"$variable": "$variable"
}
結果會是1
2
3{
"test": "test"
}
foreach and keySet
資料如下1
2
3
4
5
6
7
8
9
10
11
12{
"data": {
"book": [{
"title": "cool",
"serial": 123
}, {
"title": "hot",
"serial": 321
}]
},
"comment": "Hi"
}
我想要把他轉換成以下的格式,該怎麼用 mapping template1
2
3
4
5
6
7
8
9
10{
"book_library": [{
"name": "cool",
"number": 123
}, {
"name": "hot",
"number": 321
}],
"message": "Hi"
}
mapping template 可以這樣寫1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37#set($root = $input.path("$"))
{
// keySet 可以拿到這層所有的 key
// 這裡可以拿到 data 和 comment ($rootKey)
#foreach($rootKey in $root.keySet())
#if($rootKey == "data")
"book_library": [
#foreach($elem in $root.get($rootKey))
{
// 這層可以達到 title 和 serial
#foreach($i in $elem.keySet())
#if($i == "title")
"name": "$elem.get($i)"
#elseif($i == "serial")
// 因為要讓這裡是數字,所以不加上雙引號
"number": $elem.get($i)
#end
#if($foreach.hasNext),#end
#end
}
#if($foreach.hasNext),#end
#end
]
#elseif ($rootKey == "comment")
"message": "$root.get($rootKey)"
#end
// 這是為了讓
// {
// "test": 123
// }
// 最後面的 123 加逗點用的
// 如果是會後一個,就不會加逗點了
#if($foreach.hasNext),#end
#end
}
更好的寫法
在 aws 官網中,除了拿到 raw payload 之外
還可以利用 $input.json()
的寫法拿到格式更完整的資料
因為在原本的方式中,如果拿到的字串包含 \n
,這會讓 API Gateway 爆炸
雖然可以透過 $util.escapeJavaScript
的方式避免
但在每一個地方都加上 $util.escapeJavaScript
也是很蠢
所以新的寫法會像是這樣
第一個地方是
#set($count = $foreach.count - 1)
這是為了拿到index
第二個地方寫法就比較特別,拿到
index
之後,$input.json($)
這樣是拿到整個 payload (JSON)
如果$rootKey = 'book_library'
那這樣寫$input.json("$['$rootKey']")
等於$input.json("$['book_library']")
的寫法,就可以拿到陣列了。
那如果要拿第一個的話$input.json("$['$rootKey'][0]")
這樣就能拿到, 如果用變數取代的話,可以寫成$input.json("$['$rootKey'][$count]")
拿到陣列後,要拿陣列裡面的物件就可以這樣寫$input.json("$['$rootKey'][0]['$i']")
等同於$input.json("$['$rootKey'][0]['title']")
第三個就是讓剩餘的都直接拿出來就結束了
要特別注意的點是,不用加上 “” 在 $input.json()
外面了
因為用 $input.json()
拿的已經是完整格式了String
就是 String
,不用像上面的方式還要加上 “” 去讓他變成字串Boolean
Int
等等全部都是,也不用擔心 \n
這個出現1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44#set($root = $input.path("$"))
{
// keySet 可以拿到這層所有的 key
// 這裡可以拿到 data 和 comment ($rootKey)
#foreach($rootKey in $root.keySet())
#if($rootKey == "data")
"book_library": [
#foreach($elem in $root.get($rootKey))
{
// ============= Here =================
#set($count = $foreach.count - 1)
// ============= Here =================
// 這層可以達到 title 和 serial
#foreach($i in $elem.keySet())
// ============= Here =================
#if($i == "title")
"name": $input.json("$['$rootkey'][$count]['$i']")
#elseif($i == "serial")
"number": $input.json("$['$rootkey'][$count]['$i']")
#end
// ============= Here =================
#if($foreach.hasNext),#end
#end
}
#if($foreach.hasNext),#end
#end
]
#elseif ($rootKey == "comment")
// =============== Here ==============
"message": $input.json("$.$rootkey")
// =============== Here ==============
#end
// 這是為了讓
// {
// "test": 123
// }
// 最後面的 123 加逗點用的
// 如果是會後一個,就不會加逗點了
#if($foreach.hasNext),#end
#end
}