Fastjson升级问题

目录

Fastjson升级问题

问题背景

问题现象

问题堆栈信息

问题解决之路(思考方向)

复现问题

问题原因

问题解决

参考博客

问题背景

Fastjson版本由于存在安全漏洞,公司要求各个部门对所属应用中存在低于1.2.83版本的fastjson升级应用升级到1.2.83,即低版本fastjson升级到高版本。

问题现象


Caused by: com.alibaba.fastjson.JSONException: syntax error, expect }, actual ,

问题堆栈信息

Method: checkLogin,

exception: com.alibaba.fastjson.JSONException: syntax error, expect }, actual ,, dubbo version: 2.4.7, current host: 172.21.21.38
com.alibaba.fastjson.JSONException: syntax error, expect }, actual ,
at com.alibaba.fastjson.util.TypeUtils.castToJavaBean(TypeUtils.java:1569)
at com.alibaba.fastjson.util.TypeUtils.cast(TypeUtils.java:1127)
at com.alibaba.fastjson.util.TypeUtils.castToJavaBean(TypeUtils.java:1069)
at com.alibaba.fastjson.JSONArray.getObject(JSONArray.java:273)
at com.yao.passport.util.CommonUtil.toUserInfo(CommonUtil.java:10)
atjava.lang.Thread.run(Thread.java:745) Caused by: com.alibaba.fastjson.JSONException: syntax error, expect }, actual , at com.alibaba.fastjson.parser.DefaultJSONParser.accept(DefaultJSONParser.java:1532) at com.alibaba.fastjson.parser.deserializer.AbstractDateDeserializer.deserialze(AbstractDateDeserializer.java:161) at com.alibaba.fastjson.parser.deserializer.AbstractDateDeserializer.deserialze(AbstractDateDeserializer.java:16) at com.alibaba.fastjson.parser.deserializer.DefaultFieldDeserializer.parseField(DefaultFieldDeserializer.java:88) at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.parseField(JavaBeanDeserializer.java:1278) at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialze(JavaBeanDeserializer.java:893) at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.parseRest(JavaBeanDeserializer.java:1624) at com.alibaba.fastjson.parser.deserializer.FastjsonASMDeserializer_3_EcuserCustomer.deserialze(Unknown Source) at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialze(JavaBeanDeserializer.java:287) at com.alibaba.fastjson.parser.deserializer.DefaultFieldDeserializer.parseField(DefaultFieldDeserializer.java:88) at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.createInstance(JavaBeanDeserializer.java:1413) at com.alibaba.fastjson.util.TypeUtils.castToJavaBean(TypeUtils.java:1567) ... 75 common frames omitted

问题解决之路(思考方向)

复现问题

  1. 第一反应是从redis获取到字符串不满足fastjson格式

但是如果不是json格式,那么早就应该报问题了。

然后加日志,输出从redis中的取出的字符串,发现字符串格式正常且符合json格式:

[{"userInfo":"","jun":"","jum":"","nickName":"xxxxxx","openUserFlag":"open","userName":"xxxx","userId":"111111","yzToken":"","expiredTime":"1661338531800","token":"xxxxxx","moniPharmacistId":"","result":0,"userLeverId":1,"loginTime":"1661338531800","gltoken":"","jud":"","member":null,"userIp":"222.191.226.242","customer":{"registerIP":"","companyName":"","channel":"","source":10,"type":0,"password":"xxxxxx","province":"0","id":"xxxxxxx","modifyDate":null,"nickName":"13270162613","telephone":"","version":"","userLevelStartTime":null,"isOldUser":0,"realPassword":"","district":"","name":"","partnerType":0,"userType":"","enterCount":0,"requestTag":"","cardNumber":"","isBindMobileToWexin":0,"loginMobile":"xxxxxx","status":1,"income":0,"ipaddress":"127.0.0.1","gender":1,"city":"","openId":null,"ecUId":0,"loginEmail":"","isDeleted":0,"cellphone":"","promoCode":"","popType":0,"email":"","userLevelEndTime":null,"userLevelId":1,"createDate":{"date":21,"hours":11,"seconds":17,"month":4,"timezoneOffset":-480,"year":120,"minutes":59,"time":1590033557000,"day":4},"birthDay":null,"address":"","salt":"L1TIwT","partnerName":"","userscore":0,"baoGangUser":false,"ecUserId":xxxxxx,"userId":"","moniPharmacistId":"","lastLoginTime":null,"partnerId":""}}]

  2 . 本地复现问题

本地使用junit来模拟“将redis 存入用户数据,然后调用出错的代码取数据”这个流程,结果正常,正常,正常!结果怎么会正常呢?

开始怀疑是两个字符串不一样,对比发现字符串中createDate不一样。

json字符串中异常的createDate,如下:

 

正常的createDate,如下:

 

3. 怀疑json包混合使用导致(createDate怎么会是这种格式?)

 

createDate在类中定义的是java.util.Date类型,json成字符串怎么会是这种格式呢?

什么操作会导致它变成这样了(它到底经历了什么)?

开始怀疑net.sf.json包和fastjson混用导致的,经过验证发现,果然这种格式正是net.sf.json包中的处理方式(心里一万头羊驼奔驰)。

  1. 问题原因

net.sf.json包中的JSONArray和JSONObject会将java.util.Date类型的createDate格式化为json字符串,即

"createDate":{"date":31,"hours":18,"seconds":14,"month":4,"timezoneOffset":-480,"year":121,"minutes":53,"time":1622458394000,"day":1},

而我们实际需要的时long类型的值,或者指定日期格式的字符串。

总的来说:

项目中net.sf.json包和alibaba 混合使用,使用net.sf.json包中的类将对象格式化后存入到Redis,解析redis中的字符串却使用的fastjson。

那么怎么混用的呢?神奇的操作(听我说,谢谢你!!!)。

在一段业务中,存入redis中的用户信息使用net.sf.json包格式化为字符串的,如下:

public void setUserInfoToRedis(UserInfo userInfo, EcuserCustomer customer, int type) {

//此处的JSONArray是net.sf.json.JSONArray而不是fastjson中的

        String value = String.valueOf(JSONArray.fromObject(userInfo));

        if (type == 1) {

            String key = customer.getId() + USERINFO;

            int ttl = PassportApolloConfigUtil.getConfigIntVal("userinfoweek_expire");

            RedisUtils.set(key, value, Long.valueOf(ttl));

        } else {

            set(customer.getId(), USERINFO, value);

        }

 }


而从redis中取出字符串后,使用alibaba的fastjson解析的,如下:

 public static UserInfo toUserInfo(String value){

        return  com.alibaba.fastjson.JSONArray.parseArray(value).getObject(0,UserInfo.class);

    }

        目前看低版本支持net.sf.json和alibaba混用,但是高版本fastjson进行了优化,不再兼容,所以升级导致报错。

问题解决

通过兜底逻辑兼容解析json字符串。

(1)针对解析报错的字符串,我们就认为是net.sf.JSON包处理的,所以我们使用net.sf包下的解析。

(2)针对可以正常解析的的json字符串,我们还是使用alibaba fastjson来解析。

处理代码如下:

public static UserInfo toUserInfo(String value) {
    log.info("从redis中获取的用户信息字符串userInfoStr={}", value);
    UserInfo userInfo = null;
    try {
        userInfo = com.alibaba.fastjson.JSONArray.parseArray(value).getObject(0, UserInfo.class);
    } catch (Exception e) {
        log.error("使用fast json解析字符串异常,异常信息error={},尝试使用net.sf.json解析字符串。", e.getMessage());
        JSONArray jsonArray = JSONArray.fromObject(value);
        JSONObject jsonObject = (JSONObject) jsonArray.get(0);
        userInfo = (UserInfo) JSONObject.toBean(jsonObject, UserInfo.class);
    }
    return userInfo;
}

参考博客

1.时间Date格式转换为json后出现的问题处理_向上吧! 少年的博客-CSDN博客_date json

2.java中使用net.sf.json对json进行解析_shanliangliuxing的博客-CSDN博客

GitHub 加速计划 / fastj / fastjson
25.69 K
6.51 K
下载
FASTJSON 2.0.x has been released, faster and more secure, recommend you upgrade.
最近提交(Master分支:3 个月前 )
c942c834 - 1 年前
5bc4709b - 1 年前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐