有这样一件事

同事A提供http接口,同事B接收数据,但是其中有一个属性接收数据一直为null。

同事A在线演示,表示我查出的数据没有问题




java 忽略大小写 注解 jackson忽略大小写_反序列化


但是同事B表示 我没接到数据一定是你的接口有问题


java 忽略大小写 注解 jackson忽略大小写_set方法_02


到底是什么问题呢

按正常思维 http请求不会出现数据丢失的情况,现在是个什么情况呢,百思不得其解

通过setKGold deBug 发现数据接收的时候并没有进入set方法,这一定是没有写入数据的,难道是set方法有问题吗?一般生成方法都是开发工具自动生成 ,但是也有开发人员喜欢自己写,我删除get set之后自动生成,仔细比对后发现自动生成的 setkGold第一个字母为小写


java 忽略大小写 注解 jackson忽略大小写_Powered by 金山文档_03


赶紧测试一下,果然可以接收数据了。

但是具体是什么原因导致的呢

经过测试并查阅了一些资料得到结论

是jackson反序列化导致的这个问题,

简单来说就是反序列化的时候获取属性,除去Boolen类型都是通过set***转换来的,转换的方法为:

protected static String legacyManglePropertyName(final String basename, final int offset)
    {
        final int end = basename.length();
        if (end == offset) { // empty name, nope
            return null;
        }
        // next check: is the first character upper case? If not, return as is
        char c = basename.charAt(offset);
        char d = Character.toLowerCase(c);
        
        if (c == d) {
            return basename.substring(offset);
        }
        // otherwise, lower case initial chars. Common case first, just one char
        StringBuilder sb = new StringBuilder(end - offset);
        sb.append(d);
        int i = offset+1;
        for (; i < end; ++i) {
            c = basename.charAt(i);
            d = Character.toLowerCase(c);
            if (c == d) {
                sb.append(basename, i, end);
                break;
            }
            sb.append(d);
        }
        return sb.toString();
    }

通过代码可以看出他去寻找除去set外的小写字母,(basename=set***,offset=3 ),如果找到就把它以及后面的字母拼接返回

因为一般第一个字母都为大写嘛 第一个字母要转为小写在找之后的字母去拼接,例如setName,转换为name,第一个字母N转换为小写,继续找第二个小写字母,找到之后将其之后的ame全部拼接到n后面得到name

那么问题来了,如果第二个字母也是大写那么就会有问题,例如kGold的set方法为setKGold时,找到第二个字母发现不是小写,此时就会转换为小写并拼接得到kg后继续向下寻找o之后发现时小写全部拼接old 得到kgold这样其实是没有这个属性的,所以无法成功反序列化这个值,

当set方法为setkGold时,第一步就找到了k此时k为小写符合条件则直接返回kGold这样就可以成功反序列化

一般标准属性命名都是单词所以不会出现第二个字母就是大写的情况,但是特殊情况出现的时候第二个字母为大写一定注意set get方法,开发工具自动生成会规避这个问题,但是如果手写一定要注意第二个字母的大小写问题。

同样如果属性名首字母大写也会出现同样的问题