jolt 自定义函数实现通用接口结果体返回
程序员文章站
2022-06-01 16:22:38
...
背景:因为公司目前有个对接引擎模块,需要做到适配第三方接口返回结果参数。
如:现在我们公司现有的返回结果体如下
{
“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类路径
希望这篇文章能对各位有所帮助!!!