jolt 自定義函式實現通用介面結果體返回
阿新 • • 發佈:2021-01-19
技術標籤:技術積累
背景:因為公司目前有個對接引擎模組,需要做到適配第三方介面返回結果引數。
如:現在我們公司現有的返回結果體如下
{
“code”: 0,
“msg”: “ok”,
“data”:{}
}
A公司的第三方介面返回的結果體為
{
“status”: 200,
“notes”: “ok”,
“trades”:{}
}
B公司的第三方介面返回的結果體為
{
“code”: 1,
“message”: “ok”,
“errors”:null
}
現在的工作就是要實現通用,無論對接的公司返回的結果體是怎麼樣的,我都能通過配置將其轉換為本公司的果體。
思路如下,我們首先要利用jolt現有的功能將第三方介面結果體的值對映到欄位code、msg、data中,這個我們可以用shift來實現,但由於我們公司code為0才是成功,第三方的介面則不然可能是200或1,又或者是其他的什麼值,所以我們此時需要一個判斷,判斷對映後的code值是否為成功,如果成為則設為0。拿A公司介面為例,如果對映後的code值為200,說明此時介面返回結果為成功,我們則將其設為0,否則直接返回。但我沒找到jolt提供的比較函式,所以求人不如求己,我打算自己定以一個
由於jolt支援自定義函式,接下來我們就要動手敲程式碼。核心程式碼如下:
package tech.rongxin.oryx.test.jolt; import java.util.Collections; import java.util.HashMap; import java.util.Map; import com.bazaarvoice.jolt.ContextualTransform; import com.bazaarvoice.jolt.SpecDriven; import com.bazaarvoice.jolt.common.Optional; import com.bazaarvoice.jolt.common.tree.MatchedElement; import com.bazaarvoice.jolt.common.tree.WalkedPath; import com.bazaarvoice.jolt.modifier.OpMode; import com.bazaarvoice.jolt.modifier.TemplatrSpecBuilder; import com.bazaarvoice.jolt.modifier.function.Function; import com.bazaarvoice.jolt.modifier.spec.ModifierCompositeSpec; public class CustomizeTransform implements SpecDriven, ContextualTransform { private final ModifierCompositeSpec rootSpec; public CustomizeTransform(Object spec) { EqualsFunction equalMapping = new EqualsFunction(); Map<String,Function> functionsMap = new HashMap<>(); // 定義方法名 functionsMap.put("equals", equalMapping); functionsMap = Collections.unmodifiableMap(functionsMap); TemplatrSpecBuilder templatrSpecBuilder = new TemplatrSpecBuilder(OpMode.OVERWRITR, functionsMap); rootSpec = new ModifierCompositeSpec(ROOT_KEY, (Map<String, Object>) spec, OpMode.OVERWRITR, templatrSpecBuilder); } @Override public Object transform(Object input, Map<String, Object> context) { Map<String, Object> contextWrapper = new HashMap<>( ); contextWrapper.put( ROOT_KEY, context ); MatchedElement rootLpe = new MatchedElement( ROOT_KEY ); WalkedPath walkedPath = new WalkedPath(); walkedPath.add( input, rootLpe ); rootSpec.apply( ROOT_KEY, Optional.of( input), walkedPath, null, contextWrapper ); return input; } }
package tech.rongxin.oryx.test.jolt; import com.bazaarvoice.jolt.common.Optional; import com.bazaarvoice.jolt.modifier.function.Function; public class EqualsFunction implements Function { @Override public Optional<Object> apply(Object... objects) { //定以該方法有三個引數 if(objects[0] == null || objects[1] == null || objects[2] == null){ return Optional.empty(); } 如果前兩個引數相等,則返回第三個引數的值,否則返回一個引數的值 if(objects[0].equals(objects[1])){ return Optional.of(objects[2]); }else { return Optional.of(objects[0]); } } }
//介面返回的結果如下:
{
"status": 200,
"notes": "ok",
"trades":"呼叫成功"
}
//編寫的表示式如下:
[{
"operation": "shift",
"spec": {
"status": "code",
"notes": "msg",
"trades": "data"
}
}, {
"operation": "tech.rongxin.oryx.test.jolt.CustomizeTransform",
"spec": {
"code": "=equals(@(1,code),200,0)"
}
}]
以下是測試類
package tech.rongxin.oryx.test;
import com.bazaarvoice.jolt.Chainr;
import com.bazaarvoice.jolt.JsonUtils;
import java.util.List;
public class Test7 {
public static void main(String[] args) {
List chainrSpecJSON = JsonUtils.jsonToList("[{\n" +
"\t\"operation\": \"shift\",\n" +
"\t\"spec\": {\n" +
"\t\t\"status\": \"code\",\n" +
"\t\t\"notes\": \"msg\",\n" +
"\t\t\"trades\": \"data\"\n" +
"\t}\n" +
"}, {\n" +
"\t\"operation\": \"tech.rongxin.oryx.test.jolt.CustomizeTransform\",\n" +
"\t\"spec\": {\n" +
"\t \"code\": \"=equals(@(1,code),200,0)\"\n" +
"\t}\n" +
"}]");
Chainr chainr = Chainr.fromSpec( chainrSpecJSON );
Object inputJSON = JsonUtils.jsonToObject("{\n" +
" \"status\": 200,\n" +
" \"notes\": \"ok\",\n" +
" \"trades\":\"呼叫成功\"\n" +
"}");
Object transformedOutput = chainr.transform(inputJSON);
System.out.println( JsonUtils.toJsonString(transformedOutput) );
}
}
返回結果如下
值得注意的是如果想用到我們自定義的函式operation的型別就必須是我們編寫的CustomizeTransform類路徑
希望這篇文章能對各位有所幫助!!!