解決RestTemplate反序列化嵌套對(duì)象的問題
RestTemplate反序列化嵌套對(duì)象
假設(shè)某個(gè)接口返回的數(shù)據(jù)如下格式
{
"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
}
}仿寫一個(gè)測(cè)試接口,用于返回這種格式的數(shù)據(jù)
@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();
}方案一
一般情況下,我們會(huì)創(chuàng)建一個(gè)與服務(wù)端一致的通用值返回對(duì)象。
@Data
public class WcsR {
private String msg;
private Integer code;
private Object data;
}data的類型無法確定。
在客戶端不知道類型的情況下,我們看下data會(huì)被解析成什么
@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());
}運(yùn)行結(jié)果

看后臺(tái)的代碼我們可以知道,data是一個(gè)對(duì)象,里面有三個(gè)變量,id(整型),tasks(對(duì)象數(shù)組),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());
}結(jié)果

可以看到,數(shù)組被解析成了Arraylist, 基本類型被解析成對(duì)應(yīng)的包裝類型。
數(shù)組里面還是個(gè)對(duì)象,還會(huì)繼續(xù)幫我們解析嗎?測(cè)試代碼如下
@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());
}結(jié)果

即使再次嵌套,還是對(duì)象還是被解析成了LinkedHashMap。
可以得到結(jié)論,在沒有提供對(duì)象類型的情況下,RestTemplate默認(rèn)情況下是這么幫我們解析的:
所有的對(duì)象都解析LinkedHashMap, 數(shù)組解析為ArrayList,基本類型解析為Integer(以及其他的包裝類)。
方案二
為什么說是在“沒有提供對(duì)象類型的情況”?
這個(gè)例子中,最外層WcsR是我們自己提供的對(duì)象,假設(shè)我們提供所有的嵌套對(duì)象,
則可以定義以下對(duì)象用于接收返回值
最外層對(duì)象
@Data
public class WcsR {
private String msg;
private Integer code;
// private Object data;
private TaskDetail tasks;
}第二層對(duì)象
@Data
public class TaskDetail {
private Integer id;
private List<TaskProcess>tasks;
private Integer status;
}第三層對(duì)象
@Data
public class TaskProcess {
private Integer id;
private Integer nodeId;
private Integer status;
private String actionName;
private String wcsProcessName;
}測(cè)試類
@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));
}測(cè)試結(jié)果

這種方法也是可以的。
總結(jié)
可以看出,反序列化的方案與SpringMvc的HttpMessageConvert有點(diǎn)類似,如果你提供了對(duì)象,則會(huì)按照對(duì)象的結(jié)構(gòu)反序列化。如果沒有提供變量,則會(huì)轉(zhuǎn)化成map、List等結(jié)構(gòu)。
如果接口比較少、字段比較多,可以用第二種方案。
如果接口比較多,字段比較少,并且字段數(shù)量都比較少時(shí),為了避免定義過多的無用類,可以用第一種方案。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
不使用myeclipse注冊(cè)機(jī)得到myeclipse注冊(cè)碼的方法(myeclipse序列號(hào))
本文為大家介紹不使用myeclipse注冊(cè)機(jī)就能得到myeclipse注冊(cè)碼(序列號(hào))的方法, 運(yùn)行下面的JAVA代碼就可以了2014-01-01
IDEA編譯報(bào)錯(cuò):Error:(2048,1024) java: 找不到符號(hào)的解決方案
在使用 Lombok 的過程中,你是否曾遇到過 IDEA 編譯報(bào)錯(cuò) Error:(2048,1024) java: 找不到符號(hào)?下面就讓我們來深入剖析這一問題的根源,并給出相應(yīng)的解決方案,需要的朋友可以參考下2025-02-02
Java 利用binarySearch實(shí)現(xiàn)抽獎(jiǎng)計(jì)算邏輯
這篇文章主要介紹了Java 利用binarySearch實(shí)現(xiàn)抽獎(jiǎng)計(jì)算邏輯,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下2020-12-12
SpringBoot實(shí)現(xiàn)RabbitMQ三種使用方式
本文主要介紹了SpringBoot實(shí)現(xiàn)RabbitMQ三種使用方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07
springboot中報(bào)錯(cuò)Invalid character found in
這篇文章主要介紹了springboot中報(bào)錯(cuò)Invalid character found in the request的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09

