博主介紹:✌全網粉絲22W+,博客專家、Java領域優質創作者華為雲/阿里雲/等平台優質作者、專注於Java技術領域✌
技術範圍:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大數據、物聯網、機器學習等設計與開發。
感興趣的可以先關注收藏起來,在工作中、生活上等遇到相關問題都可以給我留言諮詢,希望幫助更多的人。
Spring Boot 返回排序後的 Map 但前端接收順序不對的解決方案
- 一、背景描述
- 二、問題原因
- 三、解決方案
- 3.1 方案1:使用有序集合代替 Map(推薦)
- 3.2 方案2:使用自定義對象包裝
- 3.3 方案3:確保使用正確的 Map 實現類
- 3.4 方案4:前端處理方案
- 四、最佳實踐建議
- 五、拓展:為什麼LinkedHashMap有時也不起作用?
一、背景描述
返回給頁面的VO中有一個List和一個Map,兩個屬性,而且都需要排序後返回,現象是List排序結果在頁面中顯示正常,而Map排序結果在頁面中顯示跟在服務器中排序後的不同。這就奇了怪了,明明是處理好排序後才返回給頁面的,但是頁面接收後就順序不一致了。
二、問題原因
- Map 的實現類問題:即使你使用了
LinkedHashMap保持順序,在 JSON 序列化過程中可能會丟失順序 - JSON 規範:標準的 JSON 對象本身是無序的鍵值對集合
- 前端處理:JavaScript 的
JSON.parse()默認不保證對象屬性的順序
三、解決方案
3.1 方案1:使用有序集合代替 Map(推薦)
@GetMapping("/sorted-data")
public ResponseEntity<List<Map.Entry<String, Object>>> getSortedData() {
Map<String, Object> data = new LinkedHashMap<>();
// 添加數據並排序
data.put("A", 1);
data.put("B", 2);
data.put("C", 3);
// 轉換為保持順序的Entry列表
List<Map.Entry<String, Object>> sortedList = new ArrayList<>(data.entrySet());
return ResponseEntity.ok(sortedList);
}
前端將收到類似這樣的結構:
[
{"key": "A", "value": 1},
{"key": "B", "value": 2},
{"key": "C", "value": 3}
]
3.2 方案2:使用自定義對象包裝
@Data // Lombok 註解
public class KeyValuePair {
private String key;
private Object value;
// 構造方法
}
@GetMapping("/sorted-data")
public ResponseEntity<List<KeyValuePair>> getSortedData() {
Map<String, Object> data = new LinkedHashMap<>();
// 添加數據
data.put("A", 1);
data.put("B", 2);
data.put("C", 3);
// 轉換為KeyValuePair列表
List<KeyValuePair> result = data.entrySet().stream()
.map(e -> new KeyValuePair(e.getKey(), e.getValue()))
.collect(Collectors.toList());
return ResponseEntity.ok(result);
}
3.3 方案3:確保使用正確的 Map 實現類
@GetMapping("/sorted-data")
public ResponseEntity<Map<String, Object>> getSortedData() {
// 使用LinkedHashMap保持插入順序
Map<String, Object> data = new LinkedHashMap<>();
// 添加數據(已排序)
data.put("A", 1);
data.put("B", 2);
data.put("C", 3);
// 配置Jackson保留Map順序
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
mapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, false);
return ResponseEntity.ok(data);
}
3.4 方案4:前端處理方案
如果必須返回 Map,可以在前端處理:
// 假設後端返回的是保持順序的LinkedHashMap序列化的JSON
fetch('/api/sorted-data')
.then(response => response.json())
.then(data => {
// 轉換為數組保持順序
const sortedArray = Object.entries(data);
console.log(sortedArray); // 這會保持順序
});
四、最佳實踐建議
- 推薦使用方案1或方案2:返回
List<Entry>或List<自定義對象>是最可靠的方式 - 避免依賴JSON對象的屬性順序:這是不符合JSON規範的
- 如果需要嚴格順序:可以在數據結構中包含順序字段
@Data
public class OrderedItem {
private int order;
private String key;
private Object value;
// 構造方法
}
@GetMapping("/sorted-data")
public ResponseEntity<List<OrderedItem>> getSortedData() {
// 實現...
}
五、拓展:為什麼LinkedHashMap有時也不起作用?
即使在Java端使用了LinkedHashMap,以下情況仍可能導致順序丟失:
- 某些JSON庫可能不保留Map順序
- 前端JavaScript引擎對對象屬性的處理
- 中間件(如網關、代理)可能重新序列化JSON
因此,使用有序的列表結構是最可靠的跨平台解決方案。
好了,今天分享到這裏。希望你喜歡這次的探索之旅!不要忘記 “點贊” 和 “關注” 哦,我們下次見!🎈
本文完結!