# 一、jolt插件介紹
## 1、jolt插件使用簡介:
jolt插件的主要作用是將一種json格式轉化爲另一種json格式,它通過使用配置文件定義轉換規則的方法,使得json轉換可配置,只要輸入的json格式是固定的就可以使用jolt進行轉換。
[[ http://jolt-demo.appspot.com/#andrewkcarter2 | jolt插件鏈接 ]]
## 2、jolt插件主要轉換方法
插件提供了5種轉換方法:
- 1、shift:主要作用是拷貝,將輸入json的某個結構拷貝到目標json。
- 2、default:主要作用是設置默認值,如果輸入json某個value不存在,則使用默認值補齊。
- 3、remove:主要作用是刪除,可以刪除輸入json結構的某個結構。
- 4、sort:對key值進行排序。
- 5、cardinality:jsonobject和jsonarray之間的切換。
目前主要用Shiftr這個類,java代碼如下:
```
Object input = JsonUtils.classpathToObject("/jolt/Shiftr/sample01/input.json"); // 讀取input.json,如果input已經是一個java對象,則可以忽略這步
Object spec = JsonUtils.classpathToObject("/jolt/Shiftr/sample01/spec.json"); // 使用Jolt自帶的JsonUtils讀取配置的轉換規則spec.json作爲一個object
Shiftr shiftr=new Shiftr(spec); // 創建shiftr對象,傳入轉化規則
Object output = shiftr.transform(input); // 轉換input,得到output
```
(NOTE)注:operation取值有shift,default,remove,cardinality,sort,每一種轉換的規則作爲spec的value。
# 二、基本通配符說明
## “*”通配符
“*”通配符(僅可以匹配input的key,不能匹配value),使用 “*”通配符的時候,需要保證輸入json具有相同的層級結構,它可以匹配某一個層級結構中的所有key,也可以匹配一個key的部分字符。
## “&”通配符
“&”通配符有兩個參數&(0,1),第一個參數0表示從input的什麼位置去找value,第二個參數1表示將找到的value放在匹配到的哪個位置。參數可以省略,&=&0=&(0)=&(0,0)。
## “$”通配符
$通配符和&通配符具有相同的語法結構,都有兩個參數,$通配符通常用法是將當前key值作爲output的value使用。
## “#”通配符
“#”通配符最有用的一點是,當input取不同值的時候,可以對output進行不同的操作,主要是賦值操作。
## “|”通配符
“|”表示“或”的邏輯,很容易理解,它只會匹配寫出的字符。
## “@”通配符
“@”通配符也有兩個參數@(0,1),"@"和"$"用法類似,不過"@"取得是指定位置的value,而“$”取的是指定位置的key。
# 三、JOLT SPEC基本寫法總結
(NOTE)注:我理解JOLT SPEC寫法需要抓住幾個關鍵點:匹配;替換,輸入; JSON節點的引用;取值(鍵,值)。
## 1、替換JSON中的關鍵字
(NOTE)注:這個例子要理解匹配與替換
Json Input:
```
{
"rating": {
"primary": {
"value": 3
},
"quality": {
"value": 3
}
}
}
```
Jolt Spec:
```
[
{
"operation": "shift",
"spec": {
"rating": {
"primary": {
"value": "Rating"
}
}
}
}
]
```
Output:
```
{
"Rating" : 3
}
```
//說明//
> 1:“規範”節點中內容就是轉換JSON的核心方法。
> 2:匹配是按照輸入JSON的樹結構,父子節點的層次,關鍵的值進行的比如例子中先匹配了 "rating",然後是 "primary"...
> 3:匹配就是爲了替換,首先是節點的替換,比如匹配到了 "rating",而JOLT Spec“rating”後的:{}就替換掉了了這個節點。
> 4:然後是鍵值的替換,比如 "value":"Rating"所以
> "value":3 - >"rating":3
> 而"rating":3替換了主要節點,替換了評級節點。
> 5:沒有匹配到的就被忽略掉。
> 6:匹配可以使用 “*”,全部匹配。
# 2、&節點位置輸入
Json Input:
```
{
"rating": {
"primary": {
"value": "3",
"max": 5
},
"quality": {
"value": 3,
"max": 5
},
"sharpness": {
"value": 7,
"max": 10
}
}
}
```
Jolt Spec:
```
[
{
"operation": "shift",
"spec": {
"rating": {
"primary": {
"value": "Rating",
"max": "RatingRange"
},
"*": {
"max": "SecondaryRatings.&1.Range",
"value": "SecondaryRatings.&1.Value",
"$": "SecondaryRatings.&1.Id"
}
}
}
}
]
```
Output:
```
{
"Rating" : "3",
"RatingRange" : 5,
"SecondaryRatings" : {
"quality" : {
"Id" : "quality",
"Range" : 5,
"Value" : 3
},
"sharpness" : {
"Id" : "sharpness",
"Range" : 10,
"Value" : 7
}
}
}
```
//說明//
(NOTE)注:&1當前所在節點的父節點(即*)匹配到的密鑰值。
> 1: “*” 匹配等級下,除主(已匹配轉換)外其餘節點。
> 2:“value”:“SecondaryRatings.&1.Value”,到此,我們大概已經瞭解,SecondaryRatings.&1.Value是輸出json的節點結構,[]表示了層級關係,&1樹結構中level0,它的level1是“*”,&1即“*”匹配到的節點鍵。
> 3:$的作用也是取關鍵值,當前 “*” 匹配到的節點的關鍵值,不同與匹配的是, “$” 等不是匹配含義時,作用爲輸入。
繼續看例子:
Json Input:
```
{
"rating": {
"primary": {
"value": 3,
"max": 5
},
"quality": {
"value": 3,
"max": 7
}
}
}
```
Jolt Spec:
```
[
{
"operation": "shift",
"spec": {
"rating": {
"*": {
"$(1)": "ratingNames[]"
}
}
}
}
]
```
Output:
```
{
"ratingNames" : [ "rating", "rating" ]
}
```
//說明//
> $等價於$(0),$(1)即當前節點的父節點的密鑰值, []的作用表示ratingNames是一個數組, “*” 匹配到了兩個節點,這兩個節點輸入$(1)到ratingNames數組。
# 3、@#通配符
Json Input:
```
{
"rating": {
"primary": 5,
"quality": 4,
"design": 5
}
}
```
Jolt Spec:
```
[
{
"operation": "shift",
"spec": {
"rating": {
"*": {
"$": "Ratings[#2].Name",
"@": "Ratings[#2].Value"
}
}
}
}
]
```
Output:
```
{
"Ratings" : [ {
"Name" : "primary",
"Value" : 5
}, {
"Name" : "quality",
"Value" : 4
}, {
"Name" : "design",
"Value" : 5
} ]
}
```
//說明//
> 1:@是取當前節點值。
> 2:$是取當前節點的關鍵值。
> 3:#2 :(畫節點樹去理解,弄清當前#在那個節點,再跳)跳到評分,訪問評級節點,統計評分有幾個子節點被匹配到了,統計數爲數組大小。
若果將#2換成#1呢(可以自己試着解析),也可以再多包裹幾層試試:
Json Input:
```
{
"rating": {
"primary": 5,
"quality": 4,
"design": 5
}
}
```
Jolt Spec:
```
[
{
"operation": "shift",
"spec": {
"rating": {
"*": {
"$": "Ratings[#1].Name",
"@": "Ratings[#1].Value"
}
}
}
}
]
```
Output:
```
{
"Ratings" : [ {
"Name" : [ "primary", "quality", "design" ],
"Value" : [ 5, 4, 5 ]
} ]
}
```
# 4、@(,)
Json Input:
```
{
"data": {
"1234": {
"clientId": "12",
"hidden": true
},
"1235": {
"clientId": "35",
"hidden": false
}
}
}
```
Jolt Spec:
```
[
{
"operation": "shift",
"spec": {
"data": {
"*": {
"hidden": {
"true": {
"#disabled": "clients.@(3,clientId)"
},
"false": {
"#enabled": "clients.@(3,clientId)"
}
}
}
}
}
}
]
```
Output:
```
{
"clients" : {
"12" : "disabled",
"35" : "enabled"
}
}
```
//說明//
> @(3,clientId)解釋:
> @取的是價值,3(畫成樹去看),
> “*”是“1234”或“1235”,取其子節點的clientId的值。
# 5、嵌套轉換
//例子說明//
```
如果clientsActive是真實的,則執行轉換
@(2,clients)的值值:true 1 clientsActive 2
{
“Lucas公司”:{
“的clientId”:“LUCAS”的成員,
“指數”:1
},
“thunder”:{
“的clientId”:“THUNDER”,
“指數”:0
}
}
```
> 對他做“*”“clientId”:“clientIds [@(1,index)]”
Json Input:
```
{
"clientsActive": true,
"clients": {
"Lucas": {
"clientId": "LUCAS",
"index": 1
},
"thunder": {
"clientId": "THUNDER",
"index": 0
}
}
}
```
Jolt Spec:
```
[
{
"operation": "shift",
"spec": {
"clientsActive": {
"true": {
"@(2,clients)": {
"*": {
"clientId": "clientIds[@(1,index)]"
}
}
}
}
}
}
]
```
Output:
```
{
"clientIds" : [ "THUNDER", "LUCAS" ]
}
```
# 6、轉義字符
Json Input:
```
{
"@context": {
"name": "https://blog.csdn.net/#name",
"ingredient": "https://blog.csdn.net/#ingredient",
"yield": "https://blog.csdn.net/#yield",
"step": {
"@id": "https://blog.csdn.net/",
"@type": "xgd:integer"
},
"xgd": "https://mail.xgd.com/"
}
}
```
Jolt Spec:
```
[
{
"operation": "shift",
"spec": {
"\\@context": {
"name": "&1.Name",
"ingredient": "&1.Inputs",
"yield": "\\@context.Makes",
"*": "&1.&"
}
}
}
]
```
Output:
```
{
"@context" : {
"Name" : "https://blog.csdn.net/#name",
"Inputs" : "https://blog.csdn.net/#ingredient",
"Makes" : "https://blog.csdn.net/#yield",
"step" : {
"@id" : "https://blog.csdn.net/",
"@type" : "xgd:integer"
},
"xgd" : "https://mail.xgd.com/"
}
}
```
# 7、利用&取關鍵值,替換原理,達到加後綴的目的
Json Input:
```
{
"Rating": 1,
"SecondaryRatings": {
"Design": 4,
"Price": 2,
"RatingDimension3": 1
}
}
```
Jolt Spec:
```
[
{
"operation": "shift",
"spec": {
"Rating": "rating-primary",
"SecondaryRatings": {
"*": "rating-&"
}
}
}
]
```
Output:
```
{
"rating-primary" : 1,
"rating-Design" : 4,
"rating-Price" : 2,
"rating-RatingDimension3" : 1
}
```
# 8、利用@實現分類取值
Json Input:
```
{
"enties": [
{
"type": "alpha",
"data": "foo"
},
{
"type": "beta",
"data": "bar"
},
{
"type": "alpha",
"data": "zoo"
}
]
}
```
Jolt Spec:
```
[
{
"operation": "shift",
"spec": {
"enties": {
"*": "@type[]"
}
}
}
]
```
Output:
```
{
"alpha" : [ {
"type" : "alpha",
"data" : "foo"
}, {
"type" : "alpha",
"data" : "zoo"
} ],
"beta" : [ {
"type" : "beta",
"data" : "bar"
} ]
}
```
> 說明按類型分類:如上alpha的數據就歸爲一類,beta的數據歸爲另一類。
# 9、轉換大小寫,值類型的轉換
Json Input:
```
{
"x": [
3,
2,
1,
"go"
],
"small": "small",
"BIG": "BIG",
"age": "18",
"people": [
{
"firstName": "Bob",
"lastName": "Smith",
"address": {
"state": null
}
},
{
"firstName": "Sterling",
"lastName": "Archer"
}
]
}
```
Jolt Spec:
```
[
{
"operation": "modify-default-beta",
"spec": {
"y": "=join(',',@(1,x))",
"z": "=join(',',@(1,x))",
"small_toUpper": "=toUpper(@(1,small))",
"BIG_toLower": "=toLower(@(1,BIG))",
"age_toInteger": "=toInteger(@(1,age))",
"people": {
"*": {
"fullName": "=concat(@(1,firstName),'',@(1,lastName))",
"address?": {
"state": "Texas"
}
}
}
}
}
]
```
Output:
```
{
"x" : [ 3, 2, 1, "go" ],
"small" : "small",
"BIG" : "BIG",
"age" : "18",
"people" : [ {
"firstName" : "Bob",
"lastName" : "Smith",
"address" : {
"state" : "Texas"
},
"fullName" : "BobSmith"
}, {
"firstName" : "Sterling",
"lastName" : "Archer",
"fullName" : "SterlingArcher"
} ],
"y" : "3,2,1,go",
"z" : "3,2,1,go",
"small_toUpper" : "SMALL",
"BIG_toLower" : "big",
"age_toInteger" : 18
}
```
> 說明:如上所述,JOLT可以實現大小寫,值類型的轉換,轉換表達式還有很多,目前這些比較常用。
# 10、 “|”通配符
> “|”表示“或”的邏輯,很容易理解,它只會匹配寫出的字符,如:
Json Input:
```
{
"reserve": {
"red_packet": {
"quantity": "10",
"color": "red",
"Color": "green"
}
}
}
```
Jolt Spec:
```
[
{
"operation": "shift",
"spec": {
"reserve": {
"red_packet": {
"quantity": "properties.quantity",
"color|Color": "last_color"
}
}
}
}
]
```
Output:
```
{
"properties" : {
"quantity" : "10"
},
"last_color" : [ "red", "green" ]
}
```
# 11、去除一個字段:
Json Input:
```
{
"_id": {
"$old": "12245677777"
},
"id": 123
}
```
Jolt Spec:
```
[
{
"operation": "shift",
"spec": {
"_id": null,
"*": "&"
}
}
]
```
Output:
```
{
"id" : 123
}
```
> 說明:不需要那個字段直接賦null即可。
# 12、default轉換
(NOTE)注:default轉換比較簡單,對應的java類是Defaultr,主要作用是預先設置一些默認值,如果input中不存在該值,則使用默認值進行補齊。
Json Input:
```
{
"reserve": {
"number": 8,
"red_packet": {
"packet_id": "10000",
"quantity": "10"
}
}
}
```
Jolt Spec:
```
[
{
"operation": "shift",
"spec": {
"reserve": {
"number": "properties.counter",
"red_packet": {
"packet_id": "properties.packet_id",
"quantity": "properties.quantity"
}
}
}
},
{
"operation": "default",
"spec": {
"type": "track",
"event": "redpacket_noregister",
"project": "coincola"
}
}
]
```
Output:
```
{
"properties" : {
"counter" : 8,
"packet_id" : "10000",
"quantity" : "10"
},
"event" : "redpacket_noregister",
"type" : "track",
"project" : "coincola"
}
```
//說明//
> 可以看到event、type、project在Input中是沒有的,我們在spec的相應位置設置了default值,在output中就展示了該值,其他值得設置也是類似的。