XML || JSON || 实体类

背景

现在大多数应用都是使用 JSON 作为数据传输的方式。但是也有其他形式的数据存在,比如 XML。本文就是我遇到的需求:把老系统返回的 XML 封装为实体类返给前台。

思考步骤

  1. JSON 操作类库很多,但是选用哪一个?
  2. 如何将 XML 转为 JSON 串?
  3. 如何将 JSON 串转为实体类

XML 转 JSON 串

jackson

为什么先介绍 jackson:这是创建 SpringBoot 项目,里面就会自带的 json 解析库。
刚开始的返参很简单,没有包含 List 之类,所以 jackson 类库就完全足够

public class JacksonTest {
    public static void main(String[] args) throws IOException {
        String xmlStr = "<ROOT><ErrorMessage>14</ErrorMessage><student><name>Ncharming</name><age>23</age></student></ROOT>";
        ObjectMapper objectMapper = new ObjectMapper();
        ObjectMapper xmlMapper = new XmlMapper();
        // 将 xml 串转为 JsonNode
        JsonNode jsonStr = xmlMapper.readTree(xmlStr);
        //获取 json String 串转为对应的实体类
        Student student = objectMapper.readValue(jsonStr.get("student").toString(), Student.class);
        System.out.println(objectMapper.writeValueAsString(student));
    }
}

相同的节点会被最后一个节点覆盖。

      String xmlStr = "<ROOT><ListStudent><student><name>Ncharming</name><age>23</age></student><student><name>charming</name><age>24</age></student></ListStudent></ROOT>";
        ObjectMapper objectMapper = new ObjectMapper();
        ObjectMapper xmlMapper = new XmlMapper();

        JsonNode jsonStr = xmlMapper.readTree(xmlStr);
        System.out.println(jsonStr);
//outPut:{"ListStudent":{"student":{"name":"charming","age":"24"}}}

所以,不用 jackson 类库来实现。

org.json

会完整的把 XML 转为 JSON 串,但是过于完整

public class OrgJsonTest {
    public static void main(String[] args) {
        String xmlStr = "<ROOT><student><name>Ncharming</name><age>23</age></student><student><name>charming</name><age>24</age></student></ROOT>";
        String jsonStr = XML.toJSONObject(xmlStr).toString();
        System.out.println(jsonStr);
    }
}
// outPut:{"ROOT":{"student":[{"name":"Ncharming","age":23},{"name":"charming","age":24}]}}

为什么说过于完整:

String complexStr = "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><student><name>Ncharming</name><age>23</age></student></soap:Envelope>";

//outPut:{"soap:Envelope":{"student":{"name":"Ncharming","age":23},"xmlns:soap":"http://schemas.xmlsoap.org/soap/envelope/"}}

当想把 XML 串转为 json 串的时候,可以用 org.json 类库实现:

  • 速度快
  • 会把相同的节点转换为 一个Array 而不会覆盖

json-lib

网上说需要自己加入很多库,但是经过我自己测试,直接在maven库找到最新的 pom ,加入到你的项目即可。

<!-- https://mvnrepository.com/artifact/net.sf.json-lib/json-lib -->
<dependency>
    <groupId>net.sf.json-lib</groupId>
    <artifactId>json-lib</artifactId>
    <version>2.4</version>
</dependency>

不过只是上面的还不能,必须加上:
<classifier>jdk15</classifier>
   long s = System.currentTimeMillis();
        XMLSerializer xmlSerializer = new XMLSerializer();
        JSON jsonStr = xmlSerializer.read(complexXmlStr);
        System.out.println(System.currentTimeMillis() - s + "," + jsonStr.toString());

测试数据可以完整转换,但是时间相对很慢,所以舍弃。

自己实现

参考链接
速度比起 org.json 大概慢了 3-4 倍,这只是我随便找的一段 XML 进行的测试

JSON 串转实体类

fastjson

fastjson WIKI
首先 fastjson 不支持 XML 转 JSON ,因为专注于 JSON 操作;
其次,宣称是 Java 实现的 JSON 类库中,性能NO.1。

我们在引用类库的时候或者一个新技术的时候,应该从全局判定,而不是某一个方面。在这里 fastjson 完全满足我的需求,并且不会因为他的一些缺点而带来困扰,所以我在项目中使用 fastjson。

public class FastjsonTest {
    public static void main(String[] args) {
        String jsonStr = "{\"student\":{\"name\":\"Ncharming\",\"age\":23}}";
        JSONObject jsonObject = JSONObject.parseObject(jsonStr);
        String stuStr = jsonObject.getJSONObject("student").toString();
        Student student = JSON.parseObject(stuStr, Student.class);
        System.out.println(student);
        //  如果 stuStr 串是一个 array 类型,那么使用如下的语句
        //  List<Student> jsonArray = JSONObject.parseArray(stuStr,Student.class);
    }
}

问题 :
我们返回的数据,可能是一个 array,也可能就是一个 Object,此时怎么办?

public class FastjsonTest {
    public static void main(String[] args) {
        String jsonStr = "{\"student\":{\"name\":\"Ncharming\",\"age\":23}}";
        JSONObject jsonObject = JSONObject.parseObject(jsonStr);
        Object stuObject = jsonObject.get("student");
        //当我们不知道 student 节点返回的是 array 还是 object
        if (stuObject instanceof JSONArray) {
            List<Student> infoList = JSONObject.parseArray(stuObject.toString(), Student.class);
            //返给前台 Resp.setInfoList()
        } else {
            Student infoList = JSON.parseObject(stuObject.toString(), Student.class);
            //返给前台 Resp.setInfo()
        }

        /**
         * 如上所见,我们对 student 节点类型进行了判断,分两种操作,这样可以解决 array 还是 object 的问题。
         * 但是引入了新问题:我们在 Resp.set 的时候,会返回到两个字段下面
         * 一旦返回到前端,当时一条数据的时候,Info 下面有值;多条数据的时候 InfoList 下面有值
         * 我们整合到一起,不管几条数据,都返回到一个字段下面去。
         */

        //解决方案,把 object 先添加到 array 中即可
        if (stuObject instanceof JSONArray) {
            List<Student> infoList = JSONObject.parseArray(stuObject.toString(), Student.class);
            //返给前台 Resp.setInfoList()
        } else {
            JSONArray jsonArray = new JSONArray();
            jsonArray.add(stuObject);
            List<Student> infoList = JSONObject.parseArray(jsonArray.toString(), Student.class);
            //返给前台 Resp.setInfoList()
        }
    }
}

总结

JSON类库本身XML转 JSONJSON 转实体类
jacksonspring-boot-starter-web包中自带的 JSON 库XmlMapper#readTree()相同节点会被覆盖,只会保留最后一个节点的内容XmlMapper#readValue() 可以转换
org.json本身方法很少,也不是特别常用1.速度快 2.转换过于完整类库中没有方法支持
fastjson阿里开源的一个类库不支持,只专注于 JSON 操作parseObject()、parseArray () 两个方法转为实体类要灵活运用

1.当然市面上还有其他很多的 JSON 类库,我这里不多介绍,比如 Gson 等。
2.本文引用了别人自己写的将 XML 转 JSON 的方法,但是效率没有类库来的高,而且也比较麻烦。
3.所有的类库包都可以通过 Maven仓库下载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值