[alibaba/fastjson]1.2.76版本处理智能转换时用到的TypeUtils.fnv1a_64_lower()方法对-和_的处理不一致导致老版本升级后不兼容

2024-09-06 34 views
3

涉及的类:com.alibaba.fastjson.util.TypeUtils.fnv1a_64_lower()

问题描述:升级fastjson版本号后对含_的key无法正常反序列化

比如我有一个如下的类:

class Person {
    @JSONField(name="person_name")
    private String personName;

    public String getPersonName() {
        return personName;
    }

    public void setPersonName(String personName) {
        this.personName = personName;
    }
}

进行如下反序列化时:

Person a = JsonUtil.fromJson("{\"person_name\":\"zhoudapeng\"}",Person.class);
Person b = JsonUtil.fromJson("{\"personName\":\"zhoudapeng\"}",Person.class);
结果如下 版本 a的personName b的personName
1.2.70 zhoudapeng zhoudapeng
1.2.76 zhoudapeng null
问题分析

fastjson有智能匹配的功能,推测是此处逻辑有改动导致的

源码分析

老版本实现:

public static long fnv1a_64_lower(String key){
        long hashCode = 0xcbf29ce484222325L;
        for(int i = 0; i < key.length(); ++i){
            char ch = key.charAt(i);
            // 老版本遇到_和-会直接跳过,所以json字符串里即使key里面含有下划线或者-也能正常反序列化成驼峰,比如 {"a_b":"xxx"} 的字符串反序列化时可用 ab,aB来接
            if(ch == '_' || ch == '-'){
                continue;
            }
            if(ch >= 'A' && ch <= 'Z'){
                ch = (char) (ch + 32);
            }
            hashCode ^= ch;
            hashCode *= 0x100000001b3L;
        }
        return hashCode;
    }

新版本实现:

public static long fnv1a_64_lower(String key){
        long hashCode = 0xcbf29ce484222325L;
        for(int i = 0; i < key.length(); ++i){
            char ch = key.charAt(i);
            <font color='red'>// 新版本对-和_的特殊处理被取消了</font>
            if(ch >= 'A' && ch <= 'Z'){
                ch = (char) (ch + 32);
            }
            hashCode ^= ch;
            hashCode *= 0x100000001b3L;
        }
        return hashCode;
    }

回答

9

我觉得这个问题是之前版本实现的BUG,如果规定了name字段,就得用name字段来进行匹配,不能加入蛇形命名和驼峰命名的转换,所以新版本的行为才是正确的,老版本的行为不正确。 @zhoudapeng

6

可以这样解释,但是这样升级的话可能会导致不兼容,既然是不兼容升级的话我觉得有必要改下大版本号,同时需要给出可能不兼容的点,否则的话从开发者看来的话是个小版本升级,大概率会直接升级版本号,然后就会遇到这类问题

3

确实,这个需要作者在更新时候进行一个版本更新文档说明,否则对于开发者来说确实整个系统就得重写,ps: 选择jackson或者gson吧

0

碰到这个bug了,人都傻了