JSON工具-JSONUtil
对象转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将字符串解析为JSONObject
JSONObject jsonObject = JSONUtil.parseObj(json);
// 演示不同取值方法:
// 1. get() 方法返回Object类型,需要手动转型
// 返回Object类型(实际是String)
Object id = jsonObject.get("id");
// 直接打印Object
System.out.println("id = " + id);
// 2. getStr() 方法直接返回String类型(自动转换,避免转型)
// 直接返回String
String 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后包装为List
User 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());
}
}
//endregion
class 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为null
String city = (address != null) ? address.getStr("city") : null;
// 5. 构建返回结果Map
// 使用HashMap存储返回字段,保证字段顺序(如果需要有序可使用LinkedHashMap)
Map<String, Object> result = new HashMap<>();
// 必填字段:name
result.put("name", name);
// 处理可能为空的city字段
if (city != null) {
// 如果city存在,直接放入结果
result.put("city", city);
} else {
// 如果city不存在,添加警告信息
result.put("city_warning", "address或city节点不存在");
}
// 6. 记录解析日志
// 在实际项目中建议使用日志框架(如SLF4J)替代System.out
System.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并转换为XML
JSONObject 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
}
}'