异构API数据处理实践

数据来源:陈同学 | 异构API数据处理实践

首先用下图阐述业务场景。

基础服务为各个业务服务(服务A/B/C) 提供API,同时基础服务数据又来源于第三方服务商。

各个服务商之间API的数据结构不同,本文不涉及不同服务商之间的安全通讯方式。

为什么需要多个服务商?

例举我所遇到的两个因素

系统稳定性考虑

以发送短信为例,若只有一个服务商,若服务商因某些因素中断服务,将导致依赖于短信的业务受到严重影响。

若对接了多个服务商,当其中一个无法使用,自动切换到可用的服务商即可。

切换服务商

因各种因素导致商务合作终止,从而切换服务商

异构数据的场景举例

先举两个例子加以说明:

  • 简单数据异构场景

    假设通过企查查、天眼查的API获取工商信息,对于企业名称字段,企业可能分别名称是ENTNAMEorg_name,有的甚至是中文字段名企业名称

  • 复杂数据异构场景

    假设对接企业ERP中财务数据,A企业可能是金蝶系统、B企业是用友系统、其他企业可能是Oracle EBS或SAP系统。

    这种场景不仅需要将异构数据处理成统一结构,而且处理过程中需要进行复杂的数据转换过程。

异构数据处理简单Demo

数据处理的目的是可以通过配置,将不同服务商的异构数据统一解析,简化代码,增强拓展性。

这里以企业工商数据做演示。下面假设三种工商信息的数据结构,均使用JSON格式展示:

数据结构示例

  • 自身标准数据结构

业务系统中以自身的数据结构为准,假设字段名称是正常翻译:

{
    "organizationName":"企业名称",
    "taxpayerNumber":"纳税人识别号"
}
  • A服务商API返回的数据结构

假设字段名称是不规则简写:

{
    "ENTNAME":"企业名称",
    "TAXNUMBER":"纳税人识别号"
}
  • B服务商API返回的数据结构

假设字段名称是中文首字母简写:

{
    "QYMC":"企业名称",
    "NSRSBH":"纳税人识别号"
}

简单处理示例

先采用简单的方式处理,首先新建一个Domain表示企业工商信息:

public class Organization {
    private String organizationName; //企业名称
    private String taxpayerNumber; //纳税人识别号
}

将A服务商的数据转换为标准数据

假设JSONObject是阿里的fastjson

// JSONObject data = {"ENTNAME":"企业名称", "TAXNUMBER":"纳税人识别号"}
Organization org = new Organization();
org.setOrganizationName(data.getString("ENTNAME"));
org.setTaxpayerNumber(data.getString("TAXNUMBER"));

将B服务商的数据转换为标准数据

// JSONObject data = {"QYMC":"企业名称", "NSRSBH":"纳税人识别号"}
Organization org = new Organization();
org.setOrganizationName(data.getString("QYMC"));
org.setTaxpayerNumber(data.getString("NSRSBH"));

上面看上去非常简单,但实际上API字段非常繁多,首先会导致大量的累赘代码,其次是有N个服务商就会有N种冗余代码。

统一解析处理示例

使用注解在Domain上标记各个服务商的对应字段

定义用于数据自动转换的注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FiledMapper {
    String serviceA() default ""; // A服务商字段
    String serviceB() default ""; // B服务商字段
}

使用注解标记Domain的属性

使用注解将异构数据的字段名与标准字段建立Mapping关系

public class Organization {
    @FiledMapper(serviceA="ENTNAME", serviceB="QYMC")
    private String organizationName; //企业名称

    @FiledMapper(serviceA="TAXNUMBER", serviceB="NSRSBH")
    private String taxpayerNumber; //纳税人识别号
}

使用反射统一解析数据

/**
 * 统一解析数据
 *
 * @param source      数据源
 * @param targetClass 目标类
 * @param serviceProvider 服务提供商
 * @return 目标类instance
 * @throws Exception
 */
public static Object parse(JSONObject source, Class targetClass, String serviceProvider) throws Exception {
    Object instance = targetClass.newInstance();
    Field[] fields = targetClass.getDeclaredFields();
    if (fields != null) {
        for (Field field : fields) {
            if (field.isAnnotationPresent(FiledMapper.class)) {
                FiledMapper filedMapper = field.getAnnotation(FiledMapper.class);
                field.setAccessible(true);
                field.set(instance, source.get("A".equals(serviceProvider) ? filedMapper.serviceA() : filedMapper.serviceB())); // 此处hardcode做演示
            }
        }
    }
    return instance;
}

数据处理测试

JSONObject dataA = JSON.parseObject("{\"ENTNAME\":\"企业A\", \"TAXNUMBER\":\"1001\"}");
JSONObject dataB = JSON.parseObject("{\"QYMC\":\"企业A\", \"NSRSBH\":\"1001\"}");
Organization orgA = (Organization) parse(dataA, Organization.class, "A");
Organization orgB = (Organization) parse(dataB, Organization.class, "B");

总结

本文仅提取了异构数据处理中的一个“点”做分析,为数据解析提供一种解决的思路。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值