记一次JSON.toJSONString()转换时非属性方法空指针异常排查及toJSONString保留null值属性

news2024/11/23 14:03:19

记一次JSON.toJSONString()转换时非属性方法空指针异常排查及toJSONString保留null值属性

异常详情

有一个类,里面有两个属性和一个类似工具的getRealName()方法如下:

getRealName()方法就是获取这个人的真实名字,如果获取不到就以name返回

class JSONTest {
        String name;
        String age;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getAge() {
            return age;
        }

        public void setAge(String age) {
            this.age = age;
        }

        public String getRealName() {
            try {
                return "real" + this.name.substring(0, 1);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return this.name;
        }
    }

然后Controller中有两个url使用了这个类,并转成JSONString返回。下面就以两个方法模仿这两个url。

public class JsonMainTest {
    public static void main(String[] args) throws Exception {
        System.out.println(method01());
        System.out.println(method02());
    }

    static String method01() {
        JSONTest jsonTest = new JSONTest();
        jsonTest.setName("lowkey");
        jsonTest.setAge("18");
        jsonTest.setName(jsonTest.getRealName());
        return JSON.toJSONString(jsonTest);
    }

    static String method02() {
        JSONTest jsonTest = new JSONTest();
        jsonTest.setAge("18");
        return JSON.toJSONString(jsonTest);
    }
}

接下来运行这个main方法,可以看到第二个方法报错了

在这里插入图片描述

异常原因

一开始很好奇为什么会异常,因为空指针,name为空了,但是我method02方法并没有调用getRealName(),为什么会调用了它,并空指针了呢。

后面细究发现是因为JSON.toJSONString()的时候是根据getter方法进行的,也就是下面这行
在这里插入图片描述

它会把所有符合以get开头的方法拿出来然后把它转成属性进行设置,所有他会在转method02方法的时候调用了getRealName()方法,而method02方法中name并没有设置值,所有才出现了空指针异常。在过程中还发现它会扫描以is开头的方法。

从打印的JSONString串也可以看出,我的属性里面并没有realName属性它却打印了出来。

解决方案

  • 第一种

    就是规范命名,与类属性无关的方法不要以get/is开头,向我这个类里面getRealName只是将name进行了处理,并不是作为一个类属性使用,所以我们将该方法改成handleRealName()或者其他即可。如下所示:再次运行便正常了,打印中也没有除属性外的字段。

    public class JsonMainTest {
        public static void main(String[] args) throws Exception {
            System.out.println(method01());
            System.out.println(method02());
        }
        static String method01() {
            JSONTest jsonTest = new JSONTest();
            jsonTest.setName("lowkey");
            jsonTest.setAge("18");
            jsonTest.setName(jsonTest.handletRealName());
            return JSON.toJSONString(jsonTest);
        }
        static String method02() {
            JSONTest jsonTest = new JSONTest();
            jsonTest.setAge("18");
            return JSON.toJSONString(jsonTest);
        }
    }
    
    class JSONTest {
        String name;
        String age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getAge() {
            return age;
        }
    
        public void setAge(String age) {
            this.age = age;
        }
    
        public String handletRealName() {
            try {
                return "real" + this.name.substring(0, 1);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return this.name;
        }
    }
    
  • 第二种

    忽略JSON转换,即在进行JSON.toJSONString的时候忽略getRealName方法。在方法上添加@JSONField(serialize = false)注解,如下所示:

    public class JsonMainTest {
        public static void main(String[] args) throws Exception {
            System.out.println(method01());
            System.out.println(method02());
        }
    
        static String method01() {
            JSONTest jsonTest = new JSONTest();
            jsonTest.setName("lowkey");
            jsonTest.setAge("18");
            jsonTest.setName(jsonTest.getRealName());
            return JSON.toJSONString(jsonTest);
        }
    
        static String method02() {
            JSONTest jsonTest = new JSONTest();
            jsonTest.setAge("18");
            return JSON.toJSONString(jsonTest);
        }
    }
    
    class JSONTest {
        String name;
        String age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getAge() {
            return age;
        }
    
        public void setAge(String age) {
            this.age = age;
        }
    
        @JSONField(serialize = false)
        public String getRealName() {
            try {
                return "real" + this.name.substring(0, 1);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return this.name;
        }
    }
    
  • 不过建议还是规范命名

其他问题:空属性不打印的情况

我们还会发现为空的属性,toJSONStirng的时候不打印。我们可以使用时添加SerializerFeature.WriteMapNullValue属性:

JSON.toJSONString(jsonTest, SerializerFeature.WriteMapNullValue);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1626605.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

小程序变更主体还要重新备案吗?

小程序迁移变更主体有什么作用?小程序迁移变更主体的作用可不止变更主体这一个哦!还可以解决一些历史遗留问题,比如小程序申请时主体不准确,或者主体发生合并、分立或业务调整等情况。这样一来,账号在认证或年审时就不…

全国各地级市财政收入支出明细统计数据2003-2022年

01、数据简介 全国各地级市财政统计主要是按地级市财政支出和财政收入两项统计,反映地区财政资金形成、分配以及使用情况的统计,​是由地区各地级市统计局统计公布,是加强财政资金管理使用的依据,研究国民收入分配和再分配的重要…

C语言----单链表的实现

前面向大家介绍了顺序表以及它的实现,今天我们再来向大家介绍链表中的单链表。 1.链表的概念和结构 1.1 链表的概念 链表是一种在物理结构上非连续,非顺序的一种存储结构。链表中的数据的逻辑结构是由链表中的指针链接起来的。 1.2 链表的结构 链表…

【Dart】双问号表达式报错的解决方案

最近准备学习一下Flutter,现从Dart开始。 Dart ??运算符报错的解决方案 报错代码如下 main() {int a;int b a ?? 123;print(b); }报错表现如下 _D05.8%20%E5%8F%8C%E9%97%AE%E5%8F%B7%E8%BF%90%E7%AE%97%E7%AC%A6.dart:3:11: Error: Non-nullable variable …

Lagent AgentLego 智能体应用搭建-作业六

本次课程由Lagent&AgentLego 核心贡献者樊奇老师讲解【Lagent & AgentLego 智能体应用搭建】课程。分别是: Agent 理论及 Lagent&AgentLego 开源产品介绍Lagent 调用已有 Arxiv 论文搜索工具实战Lagent 新增自定义工具实战(以查询天气的工具…

您的计算机已被rmallox勒索病毒感染?恢复您的数据的方法在这里!

引言: 在当今数字化时代,网络安全问题日益突出,其中勒索病毒作为一种新型的网络威胁,正逐渐引起人们的广泛关注。其中,.rmallox勒索病毒作为近期出现的一种新型恶意软件,给个人和企业带来了巨大的经济损失…

电机入门1

文章目录 122.12.22.3 33.13.23.33.4 1 2 2.1 电机板 驱动板电机分类 驱动器分类 转速 转向扭矩定时器 ADC 2.2 PID 自动控制 的核心闭环控制算是 PID的应用 2.3 无刷电机用的 可大大提高其控制效率 和控制精度 3 开发板的IO 电流太小了 20~25ma 电机要A 驱动板 信号放大没舵…

html表格(详解网页表格的制作)

一、表格介绍 HTML 表格由 <table> 标签来定义。 HTML 表格是一种用于展示结构化数据的标记语言元素。 每个表格均有若干行&#xff08;由 <tr> 标签定义&#xff09;&#xff0c;每行被分割为若干单元格&#xff08;由 <td> 标签定义&#xff09;&#x…

用卷积网络对城市住区进行分类

这将是解释我的人工智能硕士最终项目的几篇文章中的第一篇&#xff0c;我想在其中详细解释从项目的想法到结论&#xff0c;我将在其中展示给定解决方案的所有代码。 总体思路 城市扩张地图集 https://www.lincolninst.edu/es/publications/books/atlas-urban-expansion 项…

【linux】chmod权限开放(整个文件夹)

文章目录 起因权限查看权限修改 失败权限修改成功 起因 想要共享conda环境给同事&#xff0c;发现同事没权限。 权限查看 ls #查看当前目录 ls -l # 查看当前目录的东西和权限正常情况下是显示 三个rwx分别属于user&#xff0c;group&#xff0c;others 前面第一个rwx 是针…

【斐波那契】原来困扰多年的生兔子问题竟然能够轻松拿捏...万能公式法...

上篇文章我们讲解了「矩阵快速幂」技巧&#xff0c;通过快速幂极大的优化了 斐波那契数列 的求解问题。并且通过分析知道了 系数矩阵 是解决问题的关键。 本文我们继续深化对于 系数矩阵 的求解&#xff0c;介绍一种通用方法&#xff0c;一举解决所有 斐波那契及变种类型 的问…

路由器使用docker安装mysql和redis服务

路由器使用docker安装mysql和redis服务 1.先在路由器中开启docker功能 &#xff08;需要u盘 或者 移动硬盘&#xff09; 2. docker 管理地址 :http://192.168.0.1:11180/#/ 3. 拉取镜像 4. mysql容器参数设置 MYSQL_ROOT_PASSWORD 5. redis 容器设置 开发经常需要用到 &…

【工具-PyCharm】

工具-PyCharm ■ PyCharm-简介■ PyCharm-安装■ PyCharm-使用■ 修改主题■ 设置字体■ 代码模板■ 解释器配置■ 文件默认编码■ 快捷键■ 折叠■ 移动■ 注释■ 编辑■ 删除■ 查看■ 缩进■ 替换 ■ PyCharm-简介 官方下载地址 Professional&#xff1a;专业版&#xff0…

贪吃蛇撞墙功能的实现 和自动行走刷新地图 -- 第三十天

1.撞墙 1.1最初的头和尾指针要置为空&#xff0c;不然是野指针 1.2 在增加和删除节点后&#xff0c;判断是否撞墙&#xff0c;撞墙则初始话蛇 1.3在撞墙后初始化蛇&#xff0c;如果头不为空就撞墙&#xff0c;得定义临时指针指向头&#xff0c;释放头节点 2.自动刷新地图 2.1…

EMP.DLL是什么文件?EMP.DLL文件缺失怎么解决

在深入探讨计算机世界的微观结构时&#xff0c;我们会发现诸多支撑着软件正常运行的关键组件——动态链接库文件。其中&#xff0c;EMP.dll便是一个颇具代表性的例子。本文旨在全面解析EMP.dll的本质属性、功能作用以及当它丢失时可能带来的问题&#xff0c;结合实践经验&#…

9节点牛拉法matlab

潮流计算程序matlab 牛拉法 采用matlab对9节点进行潮流计算&#xff0c;采用牛拉法&#xff0c;程序运行可靠。

白平衡简介

文章目录 白平衡的概念白平衡的调节常见的白平衡模式 白平衡的概念 白平衡是指摄影、摄像和显示技术中的一项重要概念&#xff0c;用于调节图像中的白色或中性灰色的色彩&#xff0c;使其看起来在不同光源条件下都是准确的白色或灰色。白平衡的主要目的是确保图像的色彩准确性…

配置jupyter的启动路径

jupyter的安装参考&#xff1a;python环境安装jupyter-CSDN博客 1&#xff0c;背景 继上一篇python环境安装jupyter&#xff0c;里面有一个问题&#xff0c;就是启动jupyter&#xff08;命令jupyter notebook&#xff09;之后&#xff0c;页面默认显示的是启动时候的路径。 …

Synchronized关键字的深入分析

一、引言 在多线程编程中&#xff0c;正确地管理并发是确保程序正确运行的关键。Java提供了多种同步工具&#xff0c;其中synchronized关键字是最基本且最常用的同步机制之一。本文旨在深入解析synchronized的实现原理&#xff0c;探讨其在不同应用场景中的使用&#xff0c;并…

vue3第二十五节(h()函数的应用)

1、前言&#xff1a; 为什么vue 中已经有 template 模板语法&#xff0c;以及JSX了&#xff0c;还要使用 h()渲染函数&#xff1b; vue 中选择默认使用template 静态模板分析&#xff0c;有利于DMO性能的提升&#xff0c;而且更接近真实的HTML&#xff0c;便于开发设计人员理…