對象轉JSON
JSONUtil.toJsonStr
可以將任意對象(Bean、Map、集合等)直接轉換為JSON字符串。 如果對象是有序的Map等對象,則轉換后的JSON字符串也是有序的。
//region 處理POST請求,將TreeMap轉換為JSON字符串返回/*** 處理POST請求,將TreeMap轉換為JSON字符串返回* 路徑:/jsonToStr** @return 返回排序后的Map轉換成的JSON字符串*/@PostMapping("/jsonToStr") // 定義POST請求映射路徑public String jsonToStr() {// 創建一個TreeMap,它會自動按照key的自然順序排序TreeMap<Object, Object> sortedMap = new TreeMap<>();// 向Map中添加鍵值對// 添加key為"attributes",value為"a"的條目sortedMap.put("attributes", "a");// 添加key為"b",value為"b"的條目sortedMap.put("b", "b");// 添加key為"c",value為"c"的條目sortedMap.put("c", "c");System.out.println("JSONUtil.toJsonStr(sortedMap) = " + JSONUtil.toJsonStr(sortedMap));System.out.println("JSONUtil.toJsonPrettyStr(sortedMap) = " + JSONUtil.toJsonPrettyStr(sortedMap));// 使用JSONUtil工具類將Map轉換為JSON格式的字符串并返回return JSONUtil.toJsonStr(sortedMap);}//endregion
運行結果:?
//region 處理POST請求,將Map按照插入順序轉換為JSON字符串返回/*** 處理POST請求,將Map按照插入順序轉換為JSON字符串返回* 路徑:/jsonToStr** @return 返回按照插入順序排列的Map轉換成的JSON字符串*/@PostMapping("/jsonToStrOrder") // 定義POST請求映射路徑public String jsonToStrOrder() throws JsonProcessingException {// 使用LinkedHashMap,它會按照put的順序存儲鍵值對Map<Object, Object> orderedMap = new LinkedHashMap<>();// 向Map中添加鍵值對(順序會被保留)// 第1個插入orderedMap.put("attributes", "a");// 第2個插入orderedMap.put("b", "b");// 第3個插入orderedMap.put("c", "c");// 遍歷輸出,確認順序orderedMap.forEach((k, v) -> System.out.println(k + " -> " + v));ObjectMapper objectMapper = new ObjectMapper();// 禁用排序objectMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, false);return objectMapper.writeValueAsString(orderedMap);}//endregion
?運行結果:
JSON字符串解析
//region 處理POST請求,返回一個固定的JSON對象并演示JSON解析操作/*** 處理POST請求,返回一個固定的JSON對象并演示JSON解析操作* @return 返回一個預定義的JSON對象*/@PostMapping("/jsonObject")public JSONObject jsonObject() {// 定義一個多行JSON字符串(使用轉義字符保持格式)String json = "{\n" +" \"id\" : \"a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8\",\n" +" \"name\" : \"User_4821\",\n" +" \"age\" : 32,\n" +" \"isActive\" : true,\n" +" \"scores\" : [ 87, 45, 63 ],\n" +" \"address\" : {\n" +" \"street\" : \"Street 42\",\n" +" \"city\" : \"Tokyo\",\n" +" \"zipCode\" : 54321\n" +" }\n" +"}";// 使用Hutool的JSONUtil將字符串解析為JSONObjectJSONObject jsonObject = JSONUtil.parseObj(json);// 演示不同取值方法:// 1. get() 方法返回Object類型,需要手動轉型// 返回Object類型(實際是String)Object id = jsonObject.get("id");// 直接打印ObjectSystem.out.println("id = " + id);// 2. getStr() 方法直接返回String類型(自動轉換,避免轉型)// 直接返回StringString name = jsonObject.getStr("name");System.out.println("name = " + name);// 3. 獲取數值類型(使用getBigDecimal處理整數/小數)// 適合所有數值類型BigDecimal age = jsonObject.getBigDecimal("age");System.out.println("age = " + age);// 返回完整的JSON對象return jsonObject;}//endregion
運行結果:
?
//region 獲取用戶列表API/*** 獲取用戶列表API* 路徑:/getUserList** @param requestBody 請求體(可以是單個User對象或User列表)* @return 返回User對象列表** 優化說明:* 1. 支持靈活接收單個對象或集合* 2. 使用泛型方法處理不同類型輸入* 3. 增強類型安全和異常處理* 4. 規范日志記錄*/@PostMapping("/getUserList")public ResponseEntity<List<User>> getUserList(@RequestBody Object requestBody) {try {// 1. 將輸入統一轉換為JSON格式處理String jsonStr = JSONUtil.toJsonStr(requestBody);// 2. 智能判斷輸入類型(單個對象或數組)List<User> users;if (jsonStr.startsWith("[")) {// 數組情況:直接轉換為List<User>users = JSONUtil.toList(JSONUtil.parseArray(jsonStr), User.class);} else {// 單個對象情況:轉換為User后包裝為ListUser user = JSONUtil.toBean(jsonStr, User.class);users = Collections.singletonList(user);}System.out.println("users = " + JSONUtil.toJsonStr(users));// 3. 返回統一格式的成功響應return ResponseEntity.ok(users);} catch (Exception e) {return ResponseEntity.badRequest().body(Collections.emptyList());}}//endregionclass User {private String id;private String name;private int age;private boolean isActive;private List<Integer> scores;private Address address;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public boolean isActive() {return isActive;}public void setActive(boolean active) {isActive = active;}public List<Integer> getScores() {return scores;}public void setScores(List<Integer> scores) {this.scores = scores;}public Address getAddress() {return address;}public void setAddress(Address address) {this.address = address;}}class Address {private String street;private String city;private int zipCode;public String getStreet() {return street;}public void setStreet(String street) {this.street = street;}public String getCity() {return city;}public void setCity(String city) {this.city = city;}public int getZipCode() {return zipCode;}public void setZipCode(int zipCode) {this.zipCode = zipCode;}}
運行結果:
curl --request POST \--url http://localhost:8080/demo/getUserList \--header 'Accept: */*' \--header 'Accept-Encoding: gzip, deflate, br' \--header 'Connection: keep-alive' \--header 'Content-Type: application/json' \--header 'User-Agent: PostmanRuntime-ApipostRuntime/1.1.0' \--data '{"id": "a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8","name": "User_4821","age": 32,"isActive": true,"scores": [87,45,63],"address": {"street": "Street 42","city": "Tokyo","zipCode": 54321}
}'
XML字符串轉換為JSON
//region 將XML數據轉換為JSON格式的API端點/*** 將XML數據轉換為JSON格式的API端點* 路徑:/xmlToJson** @param xml 客戶端提交的XML格式字符串* @return 包含解析結果的ResponseEntity,成功時返回name和city字段,失敗時返回錯誤信息* 功能說明:* 1. 將輸入的XML字符串轉換為JSON格式* 2. 從XML結構中提取user節點的name和address下的city字段* 3. 提供完善的錯誤處理和日志記錄*/@PostMapping("/xmlToJson")public ResponseEntity<?> xmlToJson(@RequestBody String xml) {try {// 1. 將XML字符串轉換為JSONObject對象// 使用Hutool工具的JSONUtil進行轉換,自動處理XML標簽、屬性和嵌套結構JSONObject jsonObject = JSONUtil.parseFromXml(xml);// 2. 安全獲取root節點// XML轉換后的JSON對象最外層是root節點,需要先獲取這個節點// 如果root節點不存在,說明XML格式不符合預期JSONObject root = jsonObject.getJSONObject("root");if (root == null) {// 返回400錯誤,提示缺少root節點return ResponseEntity.badRequest().body(Collections.singletonMap("error", "XML格式錯誤:缺少root節點"));}// 3. 安全獲取user節點// 從root節點下獲取user節點,這是業務數據的主要容器// 如果user節點不存在,說明XML缺少關鍵數據結構JSONObject user = root.getJSONObject("user");if (user == null) {// 返回400錯誤,提示缺少user節點return ResponseEntity.badRequest().body(Collections.singletonMap("error", "XML格式錯誤:缺少user節點"));}// 4. 獲取關鍵字段:name和address.city// 4.1 直接獲取user節點下的name字段String name = user.getStr("name");// 4.2 安全獲取address節點及其city字段// 先獲取address節點對象,可能為null(如果address節點不存在)JSONObject address = user.getJSONObject("address");// 使用三元表達式安全獲取city字段,如果address不存在則city為nullString city = (address != null) ? address.getStr("city") : null;// 5. 構建返回結果Map// 使用HashMap存儲返回字段,保證字段順序(如果需要有序可使用LinkedHashMap)Map<String, Object> result = new HashMap<>();// 必填字段:nameresult.put("name", name);// 處理可能為空的city字段if (city != null) {// 如果city存在,直接放入結果result.put("city", city);} else {// 如果city不存在,添加警告信息result.put("city_warning", "address或city節點不存在");}// 6. 記錄解析日志// 在實際項目中建議使用日志框架(如SLF4J)替代System.outSystem.out.println("解析結果 - name: " + name + ", city: " + city);// 7. 返回成功響應(HTTP 200)// 使用ResponseEntity封裝返回結果和狀態碼return ResponseEntity.ok(result);} catch (Exception e) {// 全局異常處理// 捕獲所有可能的異常(XML解析異常、JSON處理異常等)// 記錄錯誤日志(實際項目應使用log.error())System.err.println("XML解析異常: " + e.getMessage());// 返回400錯誤和異常信息// 注意:生產環境可能需要過濾敏感異常信息return ResponseEntity.badRequest().body(Collections.singletonMap("error", "XML解析失敗: " + e.getMessage()));}}//endregion
運行結果:
curl --request POST \--url http://localhost:8080/demo/xmlToJson \--header 'Accept: */*' \--header 'Accept-Encoding: gzip, deflate, br' \--header 'Connection: keep-alive' \--header 'User-Agent: PostmanRuntime-ApipostRuntime/1.1.0' \--data '<?xml version="1.0" encoding="UTF-8"?>
<root><user id="1001"><name>張三</name><age>28</age><gender>男</gender><address><street>科技路123號</street><city>北京</city><zipcode>100000</zipcode></address><hobbies><hobby>游泳</hobby><hobby>編程</hobby><hobby>閱讀</hobby></hobbies></user><product><id>P1001</id><name>智能手機</name><price>3999.00</price><specs><color>黑色</color><memory>128GB</memory></specs></product><order><orderNo>ORD20230001</orderNo><date>2023-05-15</date><items><item><productId>P1001</productId><quantity>2</quantity></item></items></order>
</root>'
JSON轉換為XML
//region JSON轉XML的API端點/*** JSON轉XML的API端點* 路徑:/jsonToXml** @param json 客戶端提交的JSON格式字符串* @return 轉換后的XML字符串(成功)或錯誤信息(失敗)*/@PostMapping("/jsonToXml")public ResponseEntity<String> jsonToXml(@RequestBody String json) {// 參數校驗if (!StringUtils.hasText(json)) {return ResponseEntity.badRequest().body("錯誤:輸入JSON不能為空");}try {// 解析JSON并轉換為XMLJSONObject jsonObject = JSONUtil.parseObj(json);String xmlStr = JSONUtil.toXmlStr(jsonObject);// 驗證轉換結果if (!StringUtils.hasText(xmlStr)) {return ResponseEntity.badRequest().body("錯誤:XML轉換失敗");}// 返回成功響應return ResponseEntity.ok().header("Content-Type", "application/xml").body(xmlStr);} catch (Exception e) {// 異常處理return ResponseEntity.badRequest().body("轉換失敗: " + e.getMessage());}}//endregion
運行結果:
curl --request POST \--url http://localhost:8080/demo/jsonToXml \--header 'Accept: */*' \--header 'Accept-Encoding: gzip, deflate, br' \--header 'Connection: keep-alive' \--header 'Content-Type: application/json' \--header 'User-Agent: PostmanRuntime-ApipostRuntime/1.1.0' \--data '{"id" : "a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8","name" : "User_4821","age" : 32,"isActive" : true,"scores" : [ 87, 45, 63 ],"address" : {"street" : "Street 42","city" : "Tokyo","zipCode" : 54321}
}'