使用 fastjson 又又又翻车了,莫名其妙多了属性。。

这篇具有很好参考价值的文章主要介绍了使用 fastjson 又又又翻车了,莫名其妙多了属性。。。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

有一位同事说使用 fastjson 进行 JSON 序列化存储到数据库后,发现 JSON 字符串“莫名其妙地”多了一些属性!帮看了下代码,看到基本类型的布尔类型以 is 开头的属性,再看到 fastjson ,就有点想笑。

复现

定义 MyClass

public class MyClass {

    // boolean 类型的属性
    private boolean isActive;
    private boolean valid;

    // int 类型的属性
    private int id;

    // 默认构造器
    public MyClass() {
    }

    // 带有所有属性的构造器
    public MyClass(boolean isActive, boolean valid, int id) {
        this.isActive = isActive;
        this.valid = valid;
        this.id = id;
    }

    // isActive 的 getter 和 setter 方法
    public boolean isActive() {
        return isActive;
    }

    public void setActive(boolean isActive) {
        this.isActive = isActive;
    }

    // valid 的 getter 和 setter 方法
    public boolean getValid() {
        return valid;
    }

    public void setValid(boolean valid) {
        this.valid = valid;
    }

    // id 的 getter 和 setter 方法
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}

编写测试代码:

import com.alibaba.fastjson.JSON;

public class MyClassMain {
    public static void main(String[] args) {
        // 创建 MyClass 对象
        MyClass myClass = new MyClass(true, false, 123);

        // 使用 fastjson 序列化对象
        String jsonString = JSON.toJSONString(myClass);

        // 打印 JSON 字符串
        System.out.println(jsonString);
    }
}

结果:

{“active”:true,“id”:123,“valid”:false}

我们发现多了一个 active 属性,少了一个 isActive 属性!

推荐一个开源免费的 Spring Boot 实战项目:

https://github.com/javastacks/spring-boot-best-practice

分析

通过调试可以发现,问题出现在下面这个函数:

com.alibaba.fastjson.serializer.SerializeConfig#createJavaBeanSerializer(java.lang.Class<?>)

使用 fastjson 又又又翻车了,莫名其妙多了属性。。

public final ObjectSerializer createJavaBeanSerializer(Class<?> clazz) {
    String className = clazz.getName();
    long hashCode64 = TypeUtils.fnv1a_64(className);
    if (Arrays.binarySearch(denyClasses, hashCode64) >= 0) {
        throw new JSONException("not support class : " + className);
    }

    // 关键
    SerializeBeanInfo beanInfo = TypeUtils.buildBeanInfo(clazz, null, propertyNamingStrategy, fieldBased);
    if (beanInfo.fields.length == 0 && Iterable.class.isAssignableFrom(clazz)) {
        return MiscCodec.instance;
    }

    return createJavaBeanSerializer(beanInfo);
}

而 buildBeanInfo 的关键是com.alibaba.fastjson.util.TypeUtils#computeGetters

public static List<FieldInfo> computeGetters(Class<?> clazz, //
                                             JSONType jsonType, //
                                             Map<String,String> aliasMap, //
                                             Map<String,Field> fieldCacheMap, //
                                             boolean sorted, //
                                             PropertyNamingStrategy propertyNamingStrategy //
){
    // 省略部分代码

        if(methodName.startsWith("is")){
            if(methodName.length() < 3){
                continue;
            }
            if(returnType != Boolean.TYPE
                    && returnType != Boolean.class){
                continue;
            }
            char c2 = methodName.charAt(2);
            String propertyName;
            Field field = null;
            if(Character.isUpperCase(c2)){
                if(compatibleWithJavaBean){
                    propertyName = decapitalize(methodName.substring(2));
                } else{
                    propertyName = Character.toLowerCase(methodName.charAt(2)) + methodName.substring(3);
                }
                // 这里 isActive 的属性名被计算出 active
                propertyName = getPropertyNameByCompatibleFieldName(fieldCacheMap, methodName, propertyName, 2);
            }

            // 省略其他

             JSONField fieldAnnotation = null;
            if(field != null){
                fieldAnnotation = TypeUtils.getAnnotation(field, JSONField.class);
                if(fieldAnnotation != null){
                    if(!fieldAnnotation.serialize()){
                        continue;
                    }
                    ordinal = fieldAnnotation.ordinal();
                    serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures());
                    parserFeatures = Feature.of(fieldAnnotation.parseFeatures());
                    if(fieldAnnotation.name().length() != 0){
                        //关键: 使用 JSONField 注解设置的 name 替代属性名
                        propertyName = fieldAnnotation.name();
                        if(aliasMap != null){
                            propertyName = aliasMap.get(propertyName);
                            if(propertyName == null){
                                continue;
                            }
                        }
                    }
                    if(fieldAnnotation.label().length() != 0){
                        label = fieldAnnotation.label();
                    }
                }
            }

            // 省略部分代码

            FieldInfo fieldInfo = new FieldInfo(propertyName, method, field, clazz, null, ordinal, serialzeFeatures, parserFeatures,
                    annotation, fieldAnnotation, label);
            fieldInfoMap.put(propertyName, fieldInfo);
        }
    }
    Field[] fields = clazz.getFields();
    computeFields(clazz, aliasMap, propertyNamingStrategy, fieldInfoMap, fields);
    return getFieldInfos(clazz, sorted, fieldInfoMap);
}

其实 fastjson 通过反射虽然有能力识别真实的属性名,但是实际操作时会根据 getter 方法反推出属性名,造成转为 JSON 字符串时和实际属性名存在偏差。

解决办法

遵循阿里巴巴 Java 开发手册

孤尽老师的《Java 开发手册》 中专门强调任何布尔类型的变量都不要加 is 前缀,基本类型布尔属性反向解析时,会误以为不带 is 导致获取不到属性,抛出异常。关注公众号:Java核心技术,回复:手册,可获取高清完整版。

使用 fastjson 又又又翻车了,莫名其妙多了属性。。

使用别名

使用 fastjson 自带的 @JSONField 注解,不过这种方式 fastjson 的侵入性太强。

public class MyClass {

    @JSONField( name="isActive")
    // boolean 类型的属性
    private boolean isActive;
    private boolean valid;

    // 省略其他

}

总结

我认为 对于 Java 程序员而言,《阿里巴巴 Java 开发手册》至少读 3 遍。 工作中发现太多常见低级问题都是 《阿里巴巴 Java 开发手册》已经存在的问题。关注公众号:Java核心技术,回复:手册,可获取高清完整版。

然而推荐很多次《阿里巴巴 Java 开发手册》虽然很薄,但是很多人还是不会认真阅读几遍,导致在相同的地方跌倒很多遍。哪怕遇到类似的问题,也很容易快速想出原因。

我们遇到问题时,一定不要止步于解决问题,而是应该寻找最合理的解决方案。比如虽然加上 @JSONField 可以“解决问题”,但侵入性太强,假如其他人也用这个对象使用其他 JSON 序列化工具,就会出问题,这并不是一个好的方案。

AI 时代,遇到问题自己如果不能快速解决时,可以考虑寻求 AI 的帮助。不过使用 AI 时一定要将问题交代清楚。很多同学说的问题连其他同事都听不懂,更不别说 AI 了。

版权声明:本文为CSDN博主「明明如月学长」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/w605283073/article/details/131270338

近期热文推荐:

1.1,000+ 道 Java面试题及答案整理(2022最新版)

2.劲爆!Java 协程要来了。。。

3.Spring Boot 2.x 教程,太全了!

4.别再写满屏的爆爆爆炸类了,试试装饰器模式,这才是优雅的方式!!

5.《Java开发手册(嵩山版)》最新发布,速速下载!

觉得不错,别忘了随手点赞+转发哦!文章来源地址https://www.toymoban.com/news/detail-599676.html

到了这里,关于使用 fastjson 又又又翻车了,莫名其妙多了属性。。的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • idea 自带git down分支出现莫名其妙的文件

    是个坑   大部分场景下,会先down master 再去down 对应分支 例如dev 会出现一种内容,master里面有但dev没有当前文件,直接报错而且引入包排查没任何问题 解决方式: 用tortoiseGit  直接选对应分支。idea目前2022不支持

    2024年02月12日
    浏览(42)
  • **Unity中莫名其妙得小问题-灯光和天空盒

    Unity中莫名其妙得小问题 1、出现Lighting has been disabled in at least one Scene view.Any changes applied to lights inthe Scene will not be updated in these views until Lighting has been enabled again. 在至少一个场景视图中已禁用照明。在重新启用照明之前,将不会在这些视图中更新应用于场景中的灯光的任何更

    2024年02月12日
    浏览(58)
  • IDEA “Cannot resolve symbol”如何解决(莫名其妙爆红)

    IDEA 无法识别同一个 package 里的其他类,将其显示为红色。可以编译 compile 。鼠标放上去后显示 “Cannot resolve symbol XXX”,重启 IDEA ,重新 sync gradle,Clean build 都没有用。 多半是因为 IDEA 之前发生了错误,某些 setting 出了问题。也可能是缓存有些异常 点击菜单中的 “File”

    2024年02月08日
    浏览(48)
  • 拷贝git项目后文件权限莫名其妙被修改(mode change 100644 => 100755),该如何处理?

    把一批 git 项目从一台设备拷到另一台设备之后,未对文件做任何修改,但是进入到项目的根目录下,执行 git status 却发现所有的文件状态都是 modified 。 感觉比较诡异 执行 git diff --summary 发现大多都是 mode change 100644 = 100755 ,原来是拷贝文件的过程中,文件的权限被自动修改

    2024年02月08日
    浏览(48)
  • 解决魔兽世界wow中鼠标莫名其妙消失或自动跳回屏幕中间等类似问题整理

    魔兽世界已经离开中国大陆~~,最近在玩xxx,咳咳,突然发现一个远古问题,一直以为是自己的鼠标问题,但这么多年换了这么多台电脑,这个问题也一直存在,今天突发奇想查了一下,结果竟然有答案,还在的老铁们,试试看有用么? 玩wow的时候,鼠标有时候会突然消失,

    2024年02月11日
    浏览(448)
  • VS2019 莫名其妙出现: C2059 语法错误:“}“,C2143 语法错误:缺少“;“(在“}“的前面),C2065 未定义标识符,C2039 不是““的成员等

    一、问题 VS2019 莫名其妙出现: C2059 语法错误:\\\"}\\\" C2143 语法错误:缺少\\\";\\\"(在\\\"}\\\"的前面) C2447    “{”: 缺少函数标题(是否是老式的形式表?) C2065 未定义标识符 C2039 \\\"\\\"不是\\\"\\\"的成员 等错误,看代码其实完全没有任何问题,究竟是怎么回事呢?  二、解决办法 找到相关行附近的注

    2024年02月06日
    浏览(94)
  • Anaconda莫名其妙出现:Unable to create process using ‘C:\Users\<UserName>\.conda\envs\YOLOV5_obb\python.exe

    Unable to create process using ‘C:UsersMasterLee.condaenvsYOLOV5_obbpython.exe “C:UsersMaster Lee.condaenvsYOLOV5_obbScriptspip-script.py” install numpy’ 原因是我之前用的都是python3.7,但是今天新环境用了python3.9.而后者没有 被添加进系统环境变量。理论上应该是自动添加的啊,不知道哪里出现问

    2024年02月05日
    浏览(46)
  • android相机、相册相关(android13 适配)13又又又又又又搞事,让第三方难以生存,踩坑

    前几天公司开发的新项目要上线,结果...... 由于项目中有用户更换头像功能,应用市场经过检测android13无法更换头像,也没有崩溃也没有反应,所以App就被无情退回,相当无奈,那就查问题,手头有没有android13测试机,怎么办,怎么办,怎么办...那就想办法,还好vivo有云测

    2024年02月06日
    浏览(69)
  • 【大坑】MyBatisPlus使用updateById莫名将数据四舍五入了

    我目前在为本地的一所高中开发一个成绩分析的网站,后端使用的是SpringBoot+MyBatisPlus,业务逻辑是用户在前端上传EXCEL文件,后端从文件中读取成绩存到数据库用于分析。但是奇怪的是:在后端, 进入数据库之前的成绩数据是64.5,到数据库之后就变成了65.0 。 代码如下: 从

    2024年01月20日
    浏览(42)
  • 【导师招募】Apache DolphinScheduler 社区又又又入选开源之夏啦!

    很高兴和大家宣布,Apache DolphinScheduler 社区今年再次成功入选入选由中国科学院软件研究所开源软件供应链点亮计划发起的“ 开源之夏 ”活动。 入选公示链接 :https://mp.weixin.qq.com/s/9ExBWGoFPzZ0_SrpAcosZg 此活动旨在鼓励和引导在校学生积极参与开源软件的开发和维护,进而培养

    2024年04月11日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包