Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
zhoudapeng opened this issue May 13, 2021 · 4 comments

Comments

@zhoudapeng
Copy link

涉及的类: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;
    }
@lethal233
Copy link
Contributor

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

@zhoudapeng
Copy link
Author

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

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

@lethal233
Copy link
Contributor

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

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

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

@hei12138
Copy link

hei12138 commented Dec 3, 2021

碰到这个bug了,人都傻了

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants