警告:目前在不同的电脑测试不太稳定,庆幸小主是测试成功过的,有时候会出现中文乱码(idea工具配置有关),还有一个就是严重的问题是在解析带有数组的xml时,会将数组中的相同类型的元素当作一个解析,导致数据不完整,如本例中的student对象;
原因:springboot的版本过低导致,要求2.4.5以上;fastjson也有这样的问题,所以这里就不推荐使用它了,如果检坚持要用fastjson,可以按小主提供的1.2.76,好像1.2.75也可以,忘记了。
这里可以还有一种方式,就是引入org.json依赖 ,使用 XML.toJSONObject(String xml) 方法,解析的逻辑跟第一种纯 jackson 写法大同小异,代码虽然有点长但不复杂,如果小伙伴发现问题可以提出来,我会持续跟进。
坑一:当springboot父级工程依赖依赖版本为2.4.5时
JsonNode jsonNode = xmlMapper.readValue(newXML, JsonNode.class); 断点结果如下图
也有这样写的 JsonNode jsonNode = xmlMapper.readValue(newXML, ObjectNode.class);
由源码可知,ObjectNode是JsonNod 衍生继承类。
测试成功的依赖版本:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jt</groupId>
<artifactId>springboot_demo_4</artifactId>
<version>1.0-SNAPSHOT</version>
<!--引入父级工程-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.0</version>
<relativePath/>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--thymeleaf导入模版工具类-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--SpringMVCjar包文件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--热部署工具-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!--lombok插件-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--测试包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--引入jdbc包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--引入数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--spring整合mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.json/json -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180813</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.0</version>
</dependency>
</dependencies>
<!--负责项目打包部署-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
package com.jt.test;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import org.apache.commons.lang3.StringUtils;
import org.json.XML;
import java.util.HashMap;
import java.util.Map;
/**
* User: ldj
* Date: 2022/1/26
* Time: 21:24
* Description: xml直接转json
*/
public class XmlToJsonDemo {
public static void main(String[] args) {
//对象转xml
String xml = "<Message>" +
" <School>" +
" <SchoolName>草帽中学</SchoolName>" +
" </School>" +
" <Class>" +
" <ClassName>高三7班</ClassName>" +
" <Level>" +
" <A>1</A>" +
" <B>2</B>" +
" </Level>" +
" <Person>" +
" <Teacher>" +
" <Name>LuLu</Name>" +
" <Gender>女</Gender>" +
" <Age>23</Age>" +
" </Teacher>" +
" <Student>" +
" <Name>张三</Name>" +
" <Gender>男</Gender>" +
" <Age>16</Age>" +
" </Student>" +
" <Student>" +
" <Name>李四</Name>" +
" <Gender>男</Gender>" +
" <Age>17</Age>" +
" </Student>" +
" <Student>" +
" <Name>莉莉</Name>" +
" <Gender>女</Gender>" +
" <Age>16</Age>" +
" </Student>" +
" </Person>" +
" </Class>" +
"</Message>";
String age = "18";
int ages = Integer.parseInt(age);
System.out.println(ages);
System.out.println("\n");
System.out.println("=============================== xml -> json 分节点解析================================");
Map<String, String> responseMap = xmlToJson(xml);
String schoolJSON = responseMap.get("schoolJSON");
String classJSON = responseMap.get("classJSON");
System.out.println(schoolJSON);
System.out.println(classJSON);
System.out.println("\n");
System.out.println("=============================== xml -> json 全节点解析================================");
System.out.println(getResponseJSON(xml, "Message"));
System.out.println("\n");
System.out.println("=================================org.json 分节点解析==========================================");
Map<String, String> responseMap1 = xml2Json(xml, "Message");
String schoolJSON1 = responseMap1.get("schoolJSON");
String classJSON1 = responseMap1.get("classJSON");
System.out.println(schoolJSON1);
System.out.println(classJSON1);
System.out.println("\n");
}
//一个个节点解析
private static Map<String, String> xmlToJson(String xml) {
XmlMapper xmlMapper = new XmlMapper();
HashMap<String, String> responseMap = new HashMap<>();
try {
JsonNode jsonNode = xmlMapper.readValue(xml, JsonNode.class);
JsonNode schoolNode = jsonNode.get("School");
JsonNode classNode = jsonNode.get("Class");
ObjectMapper objectMapper = new ObjectMapper();
if (schoolNode.isContainerNode()) {
String schoolJSON = objectMapper.writeValueAsString(schoolNode);
if (StringUtils.isNotBlank(schoolJSON)) {
responseMap.put("schoolJSON", schoolJSON);
}
}
if (classNode.isContainerNode()) {
String classJSON = objectMapper.writeValueAsString(classNode);
if (StringUtils.isNotBlank(classJSON)) {
responseMap.put("classJSON", classJSON);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return responseMap;
}
//全部解析
private static String getResponseJSON(String xml, String rootTag) {
//对入参xml加根节点标签<Tag></Tag>
String s1 = "<" + rootTag + ">";
String s2 = "</" + rootTag + ">";
StringBuilder sb = new StringBuilder(xml.replaceAll("\\s*", ""));
int indexStart = sb.indexOf(s1);
sb.insert(indexStart + (s1.length()), "<Tag>");
int indexEnd = sb.indexOf(s2);
sb.insert(indexEnd, "</Tag>");
String newXML = sb.toString();
String responseJSON = null;
XmlMapper xmlMapper = new XmlMapper();
try {
//JsonNode jsonNode = xmlMapper.readValue(newXML, JsonNode.class);
JsonNode jsonNode = xmlMapper.readValue(newXML, ObjectNode.class);
JsonNode schoolNode = jsonNode.get("Tag");
ObjectMapper objectMapper = new ObjectMapper();
if (schoolNode.isContainerNode()) {
String json = objectMapper.writeValueAsString(schoolNode);
if (StringUtils.isNotBlank(json)) {
responseJSON = json;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return responseJSON;
}
//使用org.json + jackson包 或者 org.json + fastjson包<不推荐>
private static Map<String, String> xml2Json(String xml, String rootTag) {
HashMap<String, String> responseMap = new HashMap<>();
//剔除根标签Message,如果不剔除根标签Message,生成的数据结构是"Message":{.....}
if (StringUtils.isNotBlank(rootTag)) {
xml = xml.replace("<" + rootTag + ">", "");
xml = xml.replace("</" + rootTag + ">", "");
}
try {
org.json.JSONObject json = XML.toJSONObject(xml);
/**
* 由于版本问题,在解析带有数组的xml时,将数组中的相同类型的元素当作一个解析,导致数据不完整,还是用原来的jackson包
* com.alibaba.fastjson.JSONObject jsonObject = com.alibaba.fastjson.JSONObject.parseObject(json.toString());
* String schoolNode = jsonObject.getString("School");
* String classNode = jsonObject.getString("Class");
*/
/*
* 其实上面第一种方式的 XmlMapper() 是继承了 ObjectMapper 《源码》 因此下面两行代码相当于
* XmlMapper xmlMapper = new XmlMapper();
* JsonNode jsonNode = xmlMapper.readValue(xml, JsonNode.class);
* ObjectNode是JsonNod 衍生继承类
*/
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readValue(json.toString(), JsonNode.class);
if (jsonNode.isContainerNode()) {
JsonNode schoolNode = jsonNode.get("School");
JsonNode classNode = jsonNode.get("Class");
if (schoolNode.isContainerNode()) {
responseMap.put("schoolJSON", schoolNode.toString());
}
if (classNode.isContainerNode()) {
responseMap.put("classJSON", classNode.toString());
}
}
} catch (Exception e) {
e.printStackTrace();
}
return responseMap;
}
}
//jason 还可以读成Tree,不知道性能会不变高,没测试过
private static HashMap<String, String> getResponseTree(String xml){
XmlMapper xmlMapper = new XmlMapper();
HashMap<String, String> responseMap = new HashMap<>();
try {
JsonNode jsonNode = xmlMapper.readTree(xml.getBytes(StandardCharsets.UTF_8));
if(jsonNode.isContainerNode()){
JsonNode schoolNode = jsonNode.get("School");
JsonNode classNode = jsonNode.get("Class");
ObjectMapper objectMapper = new ObjectMapper();
if (schoolNode.isContainerNode()) {
//responseMap.put("schoolJSON", schoolNode.toString());
String schoolJSON = objectMapper.writeValueAsString(schoolNode);
if (StringUtils.isNotBlank(schoolJSON)) {
responseMap.put("schoolJSON", schoolJSON);
}
}
if (classNode.isContainerNode()) {
String classJSON = objectMapper.writeValueAsString(classNode);
if (StringUtils.isNotBlank(classJSON)) {
responseMap.put("classJSON", classJSON);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return responseMap;
}
我就要数字类型的而我使用第一种方式,怎么办?
String age = "18";
int ages = Integer.parseInt(age);
System.out.println(ages);
使用org.json
<!-- https://mvnrepository.com/artifact/org.json/json -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180813</version>
</dependency>
private static String xtj(String xml) {
JSONObject json = XML.toJSONObject(xml);
return json.toString();
}
如果出现中文乱码可以这样设置下