解决RestTemplate反序列化嵌套对象的问题
作者:小楼夜听雨QAQ 发布时间:2022-06-26 20:41:24
标签:RestTemplate,反序列化,嵌套,对象
RestTemplate反序列化嵌套对象
假设某个接口返回的数据如下格式
{
"msg" : "ok",
"code" : 0,
"data" : {
"id" : 1,
"tasks" : [ {
"id" : 300,
"nodeId" : 801,
"status" : 3,
"actionName" : "pick",
"wcsProcessName" : "rgv"
}, {
"id" : 301,
"nodeId" : 720,
"status" : 3,
"actionName" : "move",
"wcsProcessName" : "rgv"
}, {
"id" : 302,
"nodeId" : 720,
"status" : 3,
"actionName" : "checker",
"wcsProcessName" : "checker"
}, {
"id" : 303,
"nodeId" : 801,
"status" : 3,
"actionName" : "checker",
"wcsProcessName" : "checker"
} ],
"status" : 3
}
}
仿写一个测试接口,用于返回这种格式的数据
@PostMapping("/aiot/task/info")
public R queryTask(@RequestBody Map map) {
Integer taskId = (Integer) map.get("taskId");
Map res = new HashMap();
res.put("id", taskId);
res.put("tasks", Arrays.asList(
new TaskProcess(300, 801, 3, "pick", "rgv"),
new TaskProcess(301, 720, 3, "move", "rgv"),
new TaskProcess(302, 720, 3, "checker", "checker"),
new TaskProcess(303, 801, 3, "checker", "checker")
));
res.put("status", 3);
return R.ok(res);
}
客户端的代码如下
@Test
public void test() {
HashMap<String, Integer> map = new HashMap<>();
map.put("taskId", 1);
ResponseEntity<WcsR> wcsRResponseEntity = restTemplate.postForEntity("http://localhost:8081/aiot/task/info", map, WcsR.class);
WcsR wcsR = wcsRResponseEntity.getBody();
}
方案一
一般情况下,我们会创建一个与服务端一致的通用值返回对象。
@Data
public class WcsR {
private String msg;
private Integer code;
private Object data;
}
data的类型无法确定。
在客户端不知道类型的情况下,我们看下data会被解析成什么
@Test
public void test() {
HashMap<String, Integer> map = new HashMap<>();
map.put("taskId", 1);
ResponseEntity<WcsR> wcsRResponseEntity = restTemplate.postForEntity("http://localhost:8081/aiot/task/info", map, WcsR.class);
WcsR wcsR = wcsRResponseEntity.getBody();
System.out.println(wcsR.getData().getClass().getName());
}
运行结果
看后台的代码我们可以知道,data是一个对象,里面有三个变量,id(整型),tasks(对象数组),status(整型)。
下面尝试获取这些成员变量
@Test
public void test() {
HashMap<String, Integer> map = new HashMap<>();
map.put("taskId", 1);
ResponseEntity<WcsR> wcsRResponseEntity = restTemplate.postForEntity("http://localhost:8081/aiot/task/info", map, WcsR.class);
WcsR wcsR = wcsRResponseEntity.getBody();
System.out.println(wcsR.getData().getClass().getName());
LinkedHashMap dataMap = (LinkedHashMap) wcsR.getData();
System.out.println("id: " + dataMap.get("id").getClass().getName());
System.out.println("tasks: " + dataMap.get("tasks").getClass().getName());
System.out.println("status: " + dataMap.get("status").getClass().getName());
}
结果
可以看到,数组被解析成了Arraylist, 基本类型被解析成对应的包装类型。
数组里面还是个对象,还会继续帮我们解析吗?测试代码如下
@Test
public void test() {
HashMap<String, Integer> map = new HashMap<>();
map.put("taskId", 1);
ResponseEntity<WcsR> wcsRResponseEntity = restTemplate.postForEntity("http://localhost:8081/aiot/task/info", map, WcsR.class);
WcsR wcsR = wcsRResponseEntity.getBody();
LinkedHashMap dataMap = (LinkedHashMap) wcsR.getData();
// System.out.println("id: " + dataMap.get("id").getClass().getName());
// System.out.println("tasks: " + dataMap.get("tasks").getClass().getName());
// System.out.println("status: " + dataMap.get("status").getClass().getName());
ArrayList tasks = (ArrayList) dataMap.get("tasks");
System.out.println(tasks.get(0).getClass().getName());
}
结果
即使再次嵌套,还是对象还是被解析成了LinkedHashMap。
可以得到结论,在没有提供对象类型的情况下,RestTemplate默认情况下是这么帮我们解析的:
所有的对象都解析LinkedHashMap, 数组解析为ArrayList,基本类型解析为Integer(以及其他的包装类)。
方案二
为什么说是在“没有提供对象类型的情况”?
这个例子中,最外层WcsR是我们自己提供的对象,假设我们提供所有的嵌套对象,
则可以定义以下对象用于接收返回值
最外层对象
@Data
public class WcsR {
private String msg;
private Integer code;
// private Object data;
private TaskDetail tasks;
}
第二层对象
@Data
public class TaskDetail {
private Integer id;
private List<TaskProcess>tasks;
private Integer status;
}
第三层对象
@Data
public class TaskProcess {
private Integer id;
private Integer nodeId;
private Integer status;
private String actionName;
private String wcsProcessName;
}
测试类
@Test
public void test() {
HashMap<String, Integer> map = new HashMap<>();
map.put("taskId", 1);
ResponseEntity<WcsR> wcsRResponseEntity = restTemplate.postForEntity("http://localhost:8081/aiot/task/info", map, WcsR.class);
WcsR wcsR = wcsRResponseEntity.getBody();
System.out.println(wcsR.getData());
System.out.println(wcsR.getData().getId());
System.out.println(wcsR.getData().getTasks());
System.out.println(wcsR.getData().getStatus());
System.out.println(wcsR.getData().getTasks().get(0));
}
测试结果
这种方法也是可以的。
来源:https://blog.csdn.net/qq_37855749/article/details/117691268
0
投稿
猜你喜欢
- properties配置文件如下:human.name=Mr.Yuhuman.age=21human.gender=male如何把prope
- 本文实例讲述了C#使用ToUpper()与ToLower()方法将字符串进行大小写转换的方法。分享给大家供大家参考。具体分析如下:C#通过T
- 这篇文章主要介绍了Java如何实现支付宝电脑支付基于servlet版本,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学
- 在ibatis的xml文件里,我们去写sql语句,对应mapper类的方法,这些sql语句与控制台上没什么两样,但在有些功能上需要注意,如w
- 1、导包基于maven<dependency> <groupId>com.fasterxml.jacks
- 1.Spring中的 * 在web开发中, * 是经常用到的功能。它可以帮我们预先设置数据以及统计方法的执行效率等等。今天就来详细的谈一下s
- 方法引用和构造器引用了解了 Lambda 表达式有一段时间了,但是都没有怎么练习,一直停留在最低层次的了解程度,这对于追求技术进步的人来说确
- 本文实例为大家分享了Android自定义带圆点的半圆形进度条,供大家参考,具体内容如下仅限用于半圆形,如须要带圆点的圆形进度条,圆点会出现错
- 如下所示:public class Test{public static void main(String[] args) {
- List集合相信大家在开发过程中几乎都会用到。有时候难免会遇到集合里的数据是重复的,需要进行去除。然而,去重方式有好几种方式,你用的是哪种方
- 程序分析: 兔子的规律为数列1,1,2,3,5,8,13,21....程序设计:public class exp2{ publi
- 一、事件背景个人感觉自己做性能测试,可以说是轻车熟路了,而且工作多年一直都是这一套测试思路及体系,从未质疑过自己,也许是狮子座的迷之自信吧!
- MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注SQL本身,而不需要花费精力去处理例如注册驱
- 在我们使用mybatis plus 时, mybatis plus 可以帮我们自动封装我们的实体类用来查询添加,当我们遇见我们的尸体类名与我
- 嵌套查询使用Fluent Mybatis, 不用手写一行xml文件或者Mapper文件,在dao类中即可使用java api构造中比较复杂的
- Synchronized实现可见性原理可见性要实现共享变量的可见性,必须保证两点:线程修改后的共享变量值能够及时从工作内存刷新到主内存中其他
- 在项目中如果有些参数经常需要修改,或者后期可能需要修改,那我们最好把这些参数放到properties文件中,源代码中读取properties
- SessionFactory在Hibernate中实际上起到了一个缓冲区的作用 他缓冲了HI
- package com.abc.dao;import java.sql.Connection;import java.sql.DriverM
- 配置文件请看上篇Java实现redis https://www.jb51.net/article/190922.htm下面测试redis的集