FastJson==xml与json格式互转工具类

一、xml格式介绍

XML(eXtensible Markup Language)是一种标记语言,它的设计目的是为了存储和传输数据,而不是用于显示数据,这一点与HTML(HyperText Markup Language)不同。以下是XML的一些关键特点和用途的介绍:

  1. 自我描述性

    XML文档使用标签(tags)来描述数据的结构和含义,这些标签是自定义的,不同于HTML中的预定义标签。

    例如, < e m p l o y e e > 、 < n a m e > 、 < a g e > <employee>、<name>、<age> <employee>、<name>、<age>等都是用户定义的标签,用于表示员工信息的不同部分。

  2. 可扩展性:

    用户可以根据需要定义自己的标签集,这使得XML能够适应各种各样的数据模型。

    标签的命名不受限制,只要遵循一定的命名规则即可。

  3. 结构化数据:

    XML文档通常具有层次结构,即元素(elements)可以嵌套在其他元素内,形成树状结构。

    这种结构使得解析和处理XML数据变得相对容易。

  4. 平台和语言无关:

    XML是跨平台的,可以在任何支持XML解析器的系统上使用。

    它也是语言无关的,可以被多种编程语言处理。

  5. 数据交换的标准:

    由于其结构化和自我描述的特性,XML成为不同系统间交换数据的常见格式。

    许多API和Web服务都使用XML作为数据传输的格式。

  6. XML Schema 和 DTD:

    XML文档可以使用XML Schema(XSD)或Document Type Definitions(DTD)来定义文档的结构和数据类型,从而保证数据的一致性和有效性。

  7. 与CSS和XSLT的结合:

    尽管XML不关心数据的显示,但它可以与CSS(Cascading Style Sheets)结合来控制文档的外观。

    XSLT(XSL Transformations)则用于将XML转换成其他格式,如HTML或PDF。

  8. 配置文件:

    XML常用于应用程序的配置文件,因为它提供了清晰的数据组织方式。

  9. 解析和验证:

    存在多种库和工具(如Java的DOM, SAX, StAX等)用于解析XML文档,验证其结构和内容是否有效。

  10. 缺点:

    相比于二进制格式,XML文档通常较大,占用更多存储和传输资源。

    解析和生成XML也需要更多的计算资源。

总之,XML是一种灵活且广泛使用的数据表示和交换格式,特别是在需要结构化数据和跨系统集成的场景下。

xml格式示例:

java 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
  <!-- 书籍条目 -->
  <book id="bk101">
    <author>Gambardella, Matthew</author>
    <title>XML Developer's Guide</title>
    <genre>Computer</genre>
    <price>44.95</price>
    <publish_date>2000-10-01</publish_date>
    <description>An in-depth look at creating applications with XML.</description>
  </book>
  
  <!-- 另一本书条目 -->
  <book id="bk102">
    <author>Ralls, Kim</author>
    <title>Midnight Rain</title>
    <genre>Fantasy</genre>
    <price>5.95</price>
    <publish_date>2000-12-16</publish_date>
    <description>A former architect battles corporate zombies.</description>
  </book>
  
  <!-- 更多书籍条目可以继续添加... -->
  
</catalog>

在这个示例中,catalog是根元素,它包含了两个book元素,每个book元素都有自己的属性(如id)和子元素(如author、title等)。属性值放在引号中,并且紧跟在元素名之后,使用空格分隔。元素内容可以是纯文本,或者进一步包含其他元素。此外,注释以 包裹,用来提供非结构化的文本信息。

二、json格式介绍

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它以文本形式存储和交换数据,易于人阅读和编写,同时也易于机器解析和生成。JSON是基于JavaScript的一个子集,但它是语言无关的,可以被多种编程语言支持。以下是JSON格式的关键特点和组成部分:

  1. 对象(Object):
  • 对象在JSON中用花括号 {} 包裹。
  • 对象由零个或多个键值对(key-value pairs)组成,键值对之间用逗号 , 分隔。
  • 键(key)是字符串,用双引号 " " 包围,值(value)可以是各种数据类型,包括字符串、数字、布尔值、数组、null,甚至是另一个JSON对象。
  • 键和值之间用冒号 : 分隔,如:"key": value。
  1. 数组(Array):
  • 数组在JSON中用方括号 [] 包裹。
  • 数组由零个或多个值组成,值之间用逗号 , 分隔。
  • 数组中的值可以是任意数据类型,包括其他JSON对象或数组。
  1. 数据类型:
  • 字符串(String): 使用双引号包围,如 "example string"。
  • 数字(Number): 可以是整数或浮点数,如 42 或 3.14。
  • 布尔值(Boolean): true 或 false。
  • null: 代表空值,只有一种形式:null。
  • 空值(Empty): JSON没有单独的空值,通常用 null 表示。
  1. 语法规范:
  • 所有的键必须是字符串,且必须用双引号包围,不能用单引号。
  • JSON数据必须有正确的缩进和换行,以保持良好的可读性,但不是必需的。
  • JSON不允许包含注释,与JavaScript不同。
  1. JSON与JavaScript对象的关系:
  • 在JavaScript中,JSON格式可以直接转换为JavaScript对象,反之亦然。
  • JavaScript对象与JSON对象的区别在于JSON是字符串形式,而JavaScript对象是实际的对象实例。
  1. JSON与XML比较:
  • JSON通常比XML更紧凑,因此在网络传输中更高效。
  • JSON解析和生成通常更快,因为其语法更简单。
  • JSON更适合人类直接阅读和编写,而XML更适合机器解析和验证。
  1. JSON-LD :
    JSON-LD(JSON for Linked Data)是JSON的一个扩展,用于在Web上表示语义数据,它允许将JSON数据与RDF(Resource Description Framework)框架结合,增强了数据的互操作性。

简单数据示例:

java 复制代码
{
  "name": "John Doe",
  "age": 35,
  "isStudent": false,
  "hobbies": ["reading", "gaming"],
  "address": {
    "street": "123 Main St",
    "city": "New York",
    "country": "USA"
  }
}

三、解析工具类代码

java 复制代码
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * fastjson工具类(需要引入fastjson和dom4j的pom依赖)
 * @author hulei
 * @Date 2023/3/15 17:18
 */
public class FastJsonUtil {

    /**
     * xml转fastjson
     * @param xml 待转换数据xml字符串
     * @return JSONObject对象
     */
    public static JSONObject xmlToFastJson(String xml){
        JSONObject jsonObject = null;
        try {
            jsonObject = new JSONObject();
            Document document = DocumentHelper.parseText(xml);
            // 获取根节点元素对象
            Element root = document.getRootElement();
            iterateNodes(root, jsonObject);
        }catch (Exception e){
            return jsonObject;
        }
        return jsonObject;
    }

    /**
     * fastjson转xml
     * @param jsonStr 待转换json字符串
     * @param escape  是否忽略特殊字符(即特殊字符转xml后追加CDATA)
     * @return
     */
    public static String fastJsonToXml(String jsonStr,Boolean escape) {
        try {
            StringBuffer buffer = new StringBuffer();
            //带顺序
            JSONObject json = JSONObject.parseObject(jsonStr, Feature.OrderedField);
            jsonToXmlStr(json,buffer, escape != null && escape);
            return buffer.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * object转JSONObject
     * @param t
     * @param <T>
     * @return
     */
    public static <T> JSONObject objectToJSONObject(T  t){
        return  JSONObject.parseObject(JSON.toJSONString(t));
    }

    /**
     * json字符串转实体对象
     * @param jsonString
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T jsonStrToEntity(String jsonString,Class<T> clazz){
        return JSONObject.parseObject(jsonString,clazz);
    }

    public static void iterateNodes(Element node, JSONObject json) {
        // 获取当前元素的名称
        String nodeName = node.getName();
        // 判断已遍历的JSON中是否已经有了该元素的名称
        if (json.containsKey(nodeName)) {
            // 该元素在同级下有多个
            Object Object = json.get(nodeName);
            JSONArray array;
            if (Object instanceof JSONArray) {
                array = (JSONArray) Object;
            }
            else {
                array = new JSONArray();
                array.add(Object);
            }
            // 获取该元素下所有子元素
            List<Element> listElement = node.elements();
            if (listElement.isEmpty()) {
                // 该元素无子元素,获取元素的值
                String nodeValue = node.getTextTrim();
                array.add(nodeValue);
                json.put(nodeName, array);
                return;
            }
            // 有子元素
            JSONObject newJson = new JSONObject();
            // 遍历所有子元素
            for (Element e : listElement) {
                // 递归
                iterateNodes(e, newJson);
            }
            array.add(newJson);
            json.put(nodeName, array);
            return;
        }
        // 该元素同级下第一次遍历
        // 获取该元素下所有子元素
        List<Element> listElement = node.elements();
        if (listElement.isEmpty()) {
            // 该元素无子元素,获取元素的值
            String nodeValue = node.getTextTrim();
            json.put(nodeName, nodeValue);
            return;
        }
        // 有子节点,新建一个JSONObject来存储该节点下子节点的值
        JSONObject object = new JSONObject();
        // 遍历所有一级子节点
        for (Element e : listElement) {
            // 递归
            iterateNodes(e, object);
        }
        json.put(nodeName, object);
        return;
    }

    private static void jsonToXmlStr(JSONObject json,StringBuffer buffer,Boolean isEscape){
        Iterator<Map.Entry<String,Object>> it = json.entrySet().iterator();
        Map.Entry<String,Object> en;
        while(it.hasNext()){
            en = it.next();
            if(en.getKey().startsWith("-")){
                continue;
            }
            if(en.getKey().equals("#text")){
                //直接输出文本
                buffer.append(en.getValue());
                continue;
            }
            if(en.getValue() instanceof JSONObject){
                buffer.append("<").append(en.getKey()).append(getAttr((JSONObject) en.getValue())).append(">");
                JSONObject jo = json.getJSONObject(en.getKey());
                jsonToXmlStr(jo,buffer,isEscape);
                buffer.append("</").append(en.getKey()).append(">");
            }else if(en.getValue() instanceof JSONArray){
                JSONArray jsonArray = json.getJSONArray(en.getKey());
                for (int i = 0; i < jsonArray.size(); i++) {
                    JSONObject jsonobject =  jsonArray.getJSONObject(i);
                    buffer.append("<").append(en.getKey()).append(getAttr(jsonobject)).append(">");
                    jsonToXmlStr(jsonobject,buffer,isEscape);
                    buffer.append("</").append(en.getKey()).append(">");
                }
            }else{
                buffer.append("<").append(en.getKey()).append(">").append(isEscape ? escape(String.valueOf(en.getValue())) : String.valueOf(en.getValue())).append("</").append(en.getKey()).append(">");
            }
        }
    }

    /**
     * 拼当前节点属性
     * @param json
     * @return
     */
    private static String getAttr(JSONObject json){
        StringBuilder sb = new StringBuilder();
        for(Map.Entry<String,Object> entity:json.entrySet()){
            if(entity.getKey().startsWith("-")){
                sb.append(" ").append(entity.getKey().substring(1)).append("=\"").append(entity.getValue().toString()).append("\"");
            }
        }
        return sb.toString();
    }

    /**
     * 特殊字符pattern
     */
    private static Pattern pattern = Pattern.compile("[<>&\"',]");

    /**
     * json转xml中遇到特殊字符对内容追加![CDATA[]]
     * @param string
     * @return
     */
    private static String escape(String string) {
        return pattern.matcher(string).find() ? "<![CDATA[" + string + "]]>" : string;
    }

    /**
     * 判断是否是JSON数组
     * @param str
     * @return
     */
    public static boolean isJsonArray(String str) {
        if (str.isBlank()) {
            return false;
        }
        return isWrap(str.trim(), '[', ']');
    }

    public static boolean isWrap(CharSequence str, char prefixChar, char suffixChar) {
        if (null == str) {
            return false;
        }
        return str.charAt(0) == prefixChar && str.charAt(str.length() - 1) == suffixChar;
    }
}
相关推荐
用户37215742613514 分钟前
Java 实现 Excel 与 TXT 文本高效互转
java
浮游本尊1 小时前
Java学习第22天 - 云原生与容器化
java
渣哥3 小时前
原来 Java 里线程安全集合有这么多种
java
间彧3 小时前
Spring Boot集成Spring Security完整指南
java
间彧4 小时前
Spring Secutiy基本原理及工作流程
java
Java水解5 小时前
JAVA经典面试题附答案(持续更新版)
java·后端·面试
洛小豆7 小时前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试
前端小张同学7 小时前
服务器上如何搭建jenkins 服务CI/CD😎😎
java·后端
ytadpole7 小时前
Spring Cloud Gateway:一次不规范 URL 引发的路由转发404问题排查
java·后端
华仔啊7 小时前
基于 RuoYi-Vue 轻松实现单用户登录功能,亲测有效
java·vue.js·后端