SpringBoot将自定义对象转JSON对象问题研究
SpringBoot JSON序列化自定义对象研究
- 1. 问题描述
- 1.1 工程代码
- 1.2 测试
- 2. 问题分析
- 2.1 初步分析结论
- 2.2 实验验证结论
- 2.3 问题拓展
- 3. 结论
摘要(干货):在使用SpringBoot中通过RestController返回自定义对象时,虽然SpringBoot会将自定义的类自动转换为JSON对象并返回给客户端。在转换过程中,Spring Boot会调用自定义类中所有的getXXX方法(XXX为任意名字),如果该方法返回值不为void,那么XXX将作为该自定义的类成员返回给客户端,而该类成员的值即为getXXX方法的返回值。如果类中未出现满足条件的方法,将会抛异常。
最近在工作中需要用到Kubernetes官方提供的client-Java来操作Kubetnetes集群。但是写bug的过程,遇到了Spring Boot巨大的坑(也可能是自己太菜了。。),自己在解决过程中,逐渐总结了一个知识点,同时也是易犯的点,特此记录并分享。
1. 问题描述
1.1 工程代码
首先看一下我demo工程的部分代码(为了能够说明问题,我自己搭建了一个简单的SpringBoot工程)。
代码中涉及到几个类主要有;
- ReturnVO — 自定义的通用返回类,主要用于返回数据
- TestController — 自定义的Rest Controller,主要用于处理请求。
- MyData — 自定义的数据类,会序列化为JSON对象,并返回给客户端。
- 首先我在pom文件中引入了几个常见的依赖(都是些常规依赖,可忽略)
<dependencies>
<!-- 引入SpringBoot web-starter的依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.6.4</version></dependency>
<!-- 引入lombok工具--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.22</version></dependency></dependencies>
- 代码中编写了自定义的一个返回类(ReturnVO),代码如下:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@AllArgsConstructor
@NoArgsConstructor
@Data
public class ReturnVO {private int code; // 返回码private String message; // 返回的messageprivate Object data; // 返回的数据
}
- 代码中中的自定义类代码如下(MyData):
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MyData {// 该类中有2个成员变量分别为 name, addressprivate String name;private String address;public String getdemo(){return "hello world";}
}
- 代码中的Controller类(TestController)如下
@RestController
public class TestController {@PostMapping("/test")public ReturnVO test(){ReturnVO result = new ReturnVO();MyData data = new MyData();result.setCode(200);result.setMessage("success");result.setData(data);return result;}
}
1.2 测试
将Spring Boot代码运行,我们使用postman发送POST请求对代码进行测试。我们可以看到如下返回值:
{"code": 200,"message": "success","data": {"name": null,"address": null,"demo": "hello world"}
}
可以看到,服务端返回值中增加了一个名字为demo的属性,但是我们的MyData类病没有该成员,是Spring Boot给我们自动加上了这个成员。
2. 问题分析
2.1 初步分析结论
出现了1.2中的情况,虽然没有看Spring boot的源代码,但是初步形成一下结论:
- Spring Boot在将Java类转换为JSON对象时,是通过读取属性值的get方法来获取属性值的,如果未出现某个成员变量的get方法,那么该类成员将不会出现在JSON对象中。
- Spring Boot在将Java类转换为JSON对象时,会读取所有以getXXX命名的成员方法(前提是该方法名的返回值不能为void),并将XXX作为JSON的属性,方法的返回值作为该属性的属性值,处理完成后返回给请求端。
2.2 实验验证结论
首先,我们来验证2.1章节中的第一个结论。
在 1.1章节的代码中,我们在MyIntOrString这个类的代码中,我们用了lombok自带的@Data注解,这个注解相当于@Setter和@Getter,为我们自动创建了类成员的set和get方法,为了验证我们2.1章节中的第一个结论,我们改写一下MyData类的代码,修改后如下:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.Setter;@Setter // 将@Data注解替换为@Setter注解
@NoArgsConstructor
@AllArgsConstructor
public class MyData {private String name;private String address;public String getname(){ // name属性的get方法return "hello world";}
}
其他代码不用更改,我们重新运行代码,并对TestController进行测试,可以看到服务端返回如下信息:
{"code": 200,"message": "success","data": {"name": "hello world"}
}
通过上面的返回值我们可以看到,虽然address是My Data类的成员变量,但是因为类中没有定义它的get方法,因此在最终的返回结果中,并未出现该成员。印证了2.1中的结论。
接着,我们来验证2.1章节中的第2个结论
在 1.1章节的代码中,我们在MyIntOrString这个类的代码中,我们用了lombok自带的@Data注解,这个注解相当于@Setter和@Getter,为我们自动创建了类成员的set和get方法,为了验证我们2.1章节中的第一个结论,我们改写一下MyData类的代码,修改后如下:
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class MyData {private String name;private String address;public String getdemo(){return "hello world";}public String getname(){return "user";}public int gettime(){return 2022;}public void getAge(){}
}
上面的代码中,我们增加个getdemo方法,gettime方法,getAge方法。其中getAge方法的返回值为空。工程中其他代码不变,我们重新运行代码,并对TestController进行测试。可以得到如下的返回结果:
{"code": 200,"message": "success","data": {"name": "user","demo": "hello world","time": 2022}
}
通过上面的返回值我们可以看到,MyData类中所有getXXX命名的方法会被读取,但是由于getAge方法返回值为空,并没有出现在返回的JSON对象中。印证了2.1中的结论。
2.3 问题拓展
我们将这个问题的结论继续拓展:假设该类中没有get方法,那么程序的运行结果会是怎样的呢? ,为了验证这个结论,我们将MyData类进行继续进行改造,改造后的代码如下:
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class MyData {private String name;private String address;
}
重新运行代码,并对TestController进行测试,得出下面的结果:
{"timestamp": "2022-03-27T08:43:05.115+00:00","status": 500,"error": "Internal Server Error","path": "/test"
}
我们可以看到程序直接出错,查看程序输出的异常信息显示:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class com.sodalife.blog.eneity.MyData and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.sodalife.blog.eneity.ReturnVO["data"])at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77) ~[jackson-databind-2.13.1.jar:2.13.1]at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1300) ~[jackson-databind-2.13.1.jar:2.13.1]at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400) ~[jackson-databind-2.13.1.jar:2.13.1]at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:46) ~[jackson-databind-2.13.1.jar:2.13.1]at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:29) ~[jackson-databind-2.13.1.jar:2.13.1]at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.13.1.jar:2.13.1]
上述的错误提示告诉我们,没有用来创建BeanSerializer的serializer,进而我们可以推断,get方法是必须存在的,否则程序将会出现异常。
3. 结论
通过问题的描述与分析,我们可以初步形成一下结论:
在使用SpringBoot中返回自定义对象时,虽然SpringBoot会将自定义的类自动转换为JSON对象并返回给客户端。在转换过程中,Spring Boot会调用自定义类中所有的getXXX方法(XXX为任意名字),如果该方法返回值不为void,那么XXX将作为该自定义的类成员返回给客户端,而该类成员的值即为getXXX方法的返回值。如果类中未出现满足任何满足条件的get方法,将会抛出异常。
SpringBoot将自定义对象转JSON对象问题研究相关推荐
- jsp 将java对象转json对象 (自定义EL函数)
功能:在 jsp 页面将 java对象 转换为 json对象 (使用自定义EL函数实现) 步骤: 1. 创建 JSP EL 工具类 2. 创建 tld 文件 3. 配置 web.xml 文件 4. 完 ...
- js中自定义对象、json对象、json字符串、普通js对象 --js学习那本书上的
4.7 自定义对象 JS除了内置对象之外,还允许我们程序自己定义属于我们自己的对象,在JS中自定义对象的方式有2种:通过构造器创建对象,通过初始化器创建对象. 4.7.1 构造器创建对象(原生JS对象 ...
- js中自定义对象、json对象、json字符串、普通js对象
4.7 自定义对象 JS除了内置对象之外,还允许我们程序自己定义属于我们自己的对象,在JS中自定义对象的方式有2种:通过构造器创建对象,通过初始化器创建对象. 4.7.1 构造器创建对象(原生JS对象 ...
- JavaScript对象、JSON对象、JSON字符串的区别
一.首先看下什么是JSON JSON:JavaScript Object Natation,JavaScript对象的表现形式,已经发展成一种轻量级的数据交换格式. JavaScript对象的表现形式 ...
- java 视图对象转换,使用spring boot开发时java对象和Json对象转换的问题_JavaScript_网络编程...
将java对象转换为on对象,市面上有很多第三方jar包,如下: jackson(最常用) com.fasterxml.jackson.core jackson-databind 2.11.2 gso ...
- json字符串转换成json对象,json对象转换成字符串,值转换成字符串,字符串转成值...
json字符串转换成json对象,json对象转换成字符串,值转换成字符串,字符串转成值 原文:json字符串转换成json对象,json对象转换成字符串,值转换成字符串,字符串转成值 主要内容: 一 ...
- Java对象转换为Json对象
前言 曾几何时,XML是程序员的宠儿,是数据传输.API.AJAX应用等方面的不二选择,但自从JSON横空出世后,或者你会发觉你身边就有很多人开始抛弃XML,在他们的心目中,JSON已经完全取代了XM ...
- java对象和json对象之间互相转换
2019独角兽企业重金招聘Python工程师标准>>> import java.util.ArrayList; import java.util.Collection; import ...
- jquery:字符串转json对象,json对象转字符串
jquery:字符串转json对象,json对象转字符串 JSON字符串: var str = '{ "name": "cxh", "sex" ...
- java对象与json对象间的相互转换的方法
String json=JSON.toJSONString(user);//关键 1.简单的解析json字符串 首先将json字符串转换为json对象,然后再解析json对象,过程如下. 1 JSON ...
最新文章
- SOLID面向对象模式浅析
- 按键的c语言代码表,各种按键模式的扫描
- 复习java基础第二天(异常处理)
- python3.82版本安装_CentOS7下安装Python3和Python2并存
- C++ 类里面,函数占用存储空间问题
- c#控制台应用程序,如何实现隐藏DOS窗口
- 特征工程的宝典-《Feature Engineering for Machine Learning》翻译及代码实现
- c++11-template template Parameter
- 对qps、tps、pv、uv的理解
- Jmeter BeanShell采样器提取接口响应并传递(三)
- 基于T4模板的文档生成
- android消息提示方法自定义,Android自定义消息提示容器
- 国内外php主流开源cms汇总
- vmware安装win10并使用xshell成功连接及虚拟机中win10设置静态ip
- 「python爬虫之路day9」:实战之使用正则表达式爬取抓狂网,古诗文网信息
- 代码解读四 文件名“Ano_AttCtrl.c”
- zookeeper和kafka的SASL认证以及生产实践
- 在线 - 支持word上传的富文本编辑器
- 多文件在线压缩并下载
- Speedoffice(PPT)如何设置幻灯片大小
热门文章
- linux解锁root
- Invalid default: public abstract java.lang.Class org.mybatis.spring.annotation.MapperScan.factoryBe
- 10X单细胞空间联合分析之SPOTlight进阶版
- 6种java垃圾回收算法_Java垃圾回收算法
- 编程命名规则:驼峰命名法和匈牙利命名法
- “简单”和“勤奋”就是只围绕团队的理念和目标去工作,而不会因为其他的问题或内耗来分散团队的力量和注意力。为此,管理者要为团队创造一个积极向上、团队合作、充满激情的工作氛围。...
- 关于MongoDB连接字符串URI格式
- 2021年全球无线宽带收入大约5631.4百万美元,预计2028年达到11770百万美元,2022至2028期间,年复合增长率CAGR为12.0%
- createcompatibledc(createcompatibledc 刷新不闪屏)
- 基于web的圆通快递物流管理系统