企业微信获取审批详情之打卡补卡(json转实体类之Gson用法记录)

问题背景:在做企业微信考勤相关功能的时候,遇到把json转成实体类,通常我会使用com.alibaba.fastjson.parseObject(json,.class)。但是有些属性一直转换不过来。即使我使用了@SerializedName注解,也无法转换。

binarywang提供了一些企业微信的sdk,可以很方便的调用企业微信的接口

        <!-- 企业微信sdk -->
        <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>weixin-java-cp</artifactId>
        </dependency>

但是,最新的sdk版本中,获取审批详情时,并没有打卡补卡的数据,于是我只能自己去调用企业微信的接口。


@Slf4j
@Component
@EnableConfigurationProperties({WxCpProperties.class})
public class WxHttpUtil {


    @Resource
    private WxCpAppidProperties appidProperties;
    @Resource
    private WxCpProperties properties;

    private String corpId;
    private String corpSecret;
    private String getTokenUrl = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?";
    private String getApprovalDetailUrl = "https://qyapi.weixin.qq.com/cgi-bin/oa/getapprovaldetail?access_token=";


    /**
     * 获取access_token
     *
     * @return
     */
    public String getWxAccessToken() {

        try {
            List<WxCpProperties.AppConfig> appConfigs = properties.getAppConfigs();
            Integer checkinSp = appidProperties.getCheckinSp();
            Optional<WxCpProperties.AppConfig> config = appConfigs.stream().filter(a -> a.getAgentId().equals(checkinSp)).findFirst();
            if (config.isPresent()) {
                WxCpProperties.AppConfig appConfig = config.get();
                corpId = properties.getCorpId();
                corpSecret = appConfig.getSecret();
            }
        } catch (Exception e) {
            log.error("微信配置文件不正确");
        }

        String url = getTokenUrl + "corpid=" + corpId + "&corpsecret=" + corpSecret;

        log.info("获取企业微信access_token,url:{}", url);
        String result = HttpUtil.get(url);
        if (result != null) {
            JSONObject resultJson = JSON.parseObject(result);
            // 出错返回码,为0表示成功,非0表示调用失败
            if (resultJson.getInteger("errcode") == 0) {
                return resultJson.getString("access_token");
            } else {
                log.error("企业微信获取access_token失败,{}", resultJson.get("errmsg"));
                return "";
            }
        }
        log.info("获取企业微信access_token失败,result:{}", result);
        return "";
    }

    /**
     * 获取审批详情
     *
     * @param accessToken token
     * @param spNo        审批单号
     */
    public String getApprovalDetail(String accessToken, String spNo) {

        String url = getApprovalDetailUrl + accessToken;
        Map<String, Object> body = new HashMap<>();
        body.put("sp_no", spNo);

        String result = HttpUtil.post(url, JSONObject.toJSONString(body));
        if (result != null) {
            JSONObject resultJson = JSON.parseObject(result);
            // 出错返回码,为0表示成功,非0表示调用失败
            if (resultJson.getInteger("errcode") == 0) {
                return resultJson.toJSONString();
            } else {
                log.error("调用企业微信getApprovalDetail接口失败,{}", resultJson.get("errmsg"));
                return "";
            }
        }
        log.error("企业微信调用getApprovalDetail接口失败,{}", result);
        return "";
    }


}

这样,我们就能自己获取到企业微信的审批数据啦,但是在使用审批数据的时候,我们需要把json转成实体类,方便后续使用,这里就遇到了问题:

我不想完全自己定义接收实体类,因为属性实在太多了。于是我就继承sdk里面的实体,然后把打卡补卡属性补全,这样就相当于帮sdk打了个补丁,哈哈

@Data
@NoArgsConstructor
@AllArgsConstructor
public class MesWxCpApprovalDetailContent implements Serializable {


    /**
     * 控件名称
     */
    private String control;

    /**
     * 控件详情
     */
    private WxCpApprovalDetailContentValue value;

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class WxCpApprovalDetailContentValue extends ContentValue implements Serializable {


        /**
         * 补卡信息
         */
        @SerializedName("punch_correction")
        private punchCorrection punchCorrection;

        @Data
        @NoArgsConstructor
        @AllArgsConstructor
        public class punchCorrection implements Serializable {
            /**
             * 异常状态说明
             */
            private String state;
            /**
             * 补卡时间,Unix时间戳
             */
            private long time;
            /**
             * 未知
             */
            private String date;
        }
    }
}

然后再使用fastjson.parseObject把接口返回的json转成我们定义的补丁实体类,大功告成!!!

NONONO,正当此时,我发现sdk缺失的打卡补卡数据有了,但其他数据好像没了。。。

 怎么会这样?原来sdk里面的实体属性和接口返回的属性名称不对应,比如:

 

 但是,他不是定义了@SerializedName("sp_name")这样的别名吗?我自己也使用了@SerializedName注解,通过fastjson.parseObject是能接收过来的呀?一脸懵逼。。。

在接下来的一段时间里,我在疯狂逼问度娘,为什么继承会导致@SerializedName注解失效?

然而并没有得到想要的答案,笑死,然后我做了一个惊为天人的操作,我使用jsonString.replace方法,把接口结果里面转换不了的属性改成一样的属性名称,这也是不得已而为之的方法,哈哈,大功告成!!!

等等。。。

@SerializedName("value")
private List<ContentTitle> values;

replace其他唯一属性的时候,都得到了想要大的结果,转换成功,但,这个sdk怎么连value都能有好几种叫法?接口里面value可太多了,这下可就不好replace了

 怎么办?我还想通过replace正则表达式来替换指定位置的value,然而不行,越搞越复杂。而且这样写代码谁能看得懂!

最后,经过学长点拨,原来一开始就错了,Gson和fastjosn是不同的工具类,

@SerializedName是Gson的写法,fastjosn当然不能识别。

 Gson有自己转json到实体类的方法:

Type type = new TypeToken<MesWxCpApprovalDetailResult>() {
                    }.getType();
                    MesWxCpApprovalDetailResult mesWxCpApprovalDetailResult = new Gson().fromJson(approvalDetail, type);
//JSONObject.parseObject(approvalDetail,MesWxCpApprovalDetailResult.class);

恍然大悟。。。

最后,有个问题,我自己写的实体类的属性用

@SerializedName

,为什么可以通过fastjson转换到实体里面?继承过来的属性为啥就不能识别?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值