背景:因为公司目前有个对接引擎模块,需要做到适配第三方接口返回结果参数。
如:现在我们公司现有的返回结果体如下
{
“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.mon.Optional;import com.mon.tree.MatchedElement;import com.mon.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);}@Overridepublic 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.mon.Optional;import com.bazaarvoice.jolt.modifier.function.Function;public class EqualsFunction implements Function {@Overridepublic 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类路径
希望这篇文章能对各位有所帮助!!!