4-8 XML与JSON

XML概述

  • 可扩展标记语言:

    • xml与平台无关,是一门独立的标记语言。与任何编程语言无关。
    • xml具有自我描述性,能够清晰地展现其特性。
    • xml数据不一定是文件形式存储,也可以在内存中构建xml数据。
    • Java编程语言是为了解决人和机器的交流问题,而xml是为了解决程序与程序之间的交流问题。
  • XML应用场景:
    • 网络数据传输(不常用):

      • 原始数据传输或者加特定字符分隔,可能带来各种问题,例如特定字符无法传输的问题。
      • 虽然Java可以采用序列化的方式进行流传输,但是这并不适用于其他编程语言。
      • 为了统一格式并且适配于更多情况下的数据格式表示,引入了XML和JSON的标记语言。
    • 数据存储:(基本不用)
    • 配置文件:(常用)XML适用于小数据的应用场景例如配置文件,当数据量很大时,使用JSON性能更高。

XML格式

  • 自我描述部分,如版本和编码方式:

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- 注释不能写在文档文档声明前 -->
    
  • 标记部分:用于表示数据使用的格式:

    <!--标记 ( 元素 / 标签 / 节点) XML文档,由一个个的标记组成.语法:开始标记(开放标记): <标记名称>结束标记(闭合标记): </标记名称>标记名称:  自定义名称,必须遵循以下命名规则:
    1.名称可以含字母、数字以及其他的字符
    2.名称不能以数字或者标点符号开始
    3.名称不能以字符 “xml”(或者 XML、Xml)开始
    4.名称不能包含空格,不能包含冒号(:)
    5.名称区分大小写标记内容:  开始标记与结束标记之间 ,是标记的内容.例如 ,我们通过标记, 描述一个人名:<name>李伟杰</name>
    6.名称可以重名,包括同层名称也可以重复
    -->
    
  • 有且必须有仅有一个根标记:

    <!--正确例子:-->
    <names><name>张三</name><name>李四</name>
    </names>
    <!--错误例子:两个根
    <name>李四</name>
    <name>麻子</name>
    -->
    
  • 标记可以嵌套,但不能交叉,即有层级关系。

    <!--举一个反例:第二层中就没有层级关系,属于交叉关系
    错误例子:存在交叉关系
    <person><name>李四<age></name>18</age>
    </person>
    -->
    
  • 标记除了开始和结束外,还可以有属性(同一个标签里<属性>的属性名不能重复):

    <!--标记中的属性, 在标记开始时 描述, 由属性名和属性值 组成.格式:在开始标记中, 描述属性.可以包含0-n个属性, 每一个属性是一个键值对!属性名不允许重复 , 键与值之间使用等号连接, 多个属性之间使用空格分割.属性值 必须被引号引住.案例:--><persons><person id="10001" groupid="1"><name>李四</name><age>18</age></person><person id="10002" groupid="1"><name>李四</name><age>20</age></person></persons>
    
  • 注释格式:

    <!--
    注释不能写在文档文档声明前
    注释不能嵌套注释格式:注释开始:  “<!--”注释结束:  如下图标所示
    -->
    
  • 语法进阶CDATA(了解):

    • 其实就是提供了类似编程语言中的转义功能,将某个特殊字符转义为普通字符。

    • 其底层逻辑是,xml解析器在碰到一定格式<![CDATA[开头和]]>结束的符号时当成普通字符忽略。

      <names><name>张三<![CDATA[<name>李四</name>]]></name>
      </names>
      
  • 命名空间(框架中才会使用):

    • 引入的目的:XML命名空间提供避免元素命名冲突的方法。
    • 本质问题:和Java中的package的概念是一样的。
    • 基本格式:特定的符号:你的前缀="你的命名空间地址"

Java操作XML(掌握)

  • 两大解析方法:SAX解析和DOM解析

    • SAX解析:

      • 逐行读取解析,对空间的内存需求不大,解析完上一行再解析下一行。
      • 每解析到一个标签就触发一次事件,如果已经得到需要的数据,就不必继续解析了。
      • 解析方向是单向的,前面解析过的数据已经被释放无法获取。
      • 无法获取层级关系,只能由程序员自己去维护。
      • 只读解析方式,无法修改XML文档内容。
    • DOM解析:
      • 用于平台无关的方式表示XML文档,需要全部读取,对内存需求量大
      • 在内存中建立文档树模型,不再使用原XML文档,可以完成数据的读写
      • 由于实际应用场景中,xml文件很小,因此内存需求大的缺点可以忽略
  • 基于DOM解析的另外两种方法:

    • JDOM解析:为Java定制模型

      • 大量使用了Java集合,方便Java开发。
      • 使用具体类而不是接口,简化了DOM的API。
      • 不是接口,灵活性也就降低了。
    • DOM4J解析:
      • 它是JDOM的一种智能分支。它合并了许多超出基本XML文档表示的功能,包括集成的XPath支持、XML Schema支持以及用于大文档或流化文档的基于事件的处理。
      • 它还提供了构建文档表示的选项,读取节点就想操作文件路径一样方便。
  • DOM4J解析(掌握)

    • 首先导入dom4j.jar包。

    • Node接口的子孙:DocumentElement

      • SAXReader用于从输入流(可以是文件或网络)中获取XML文档对象。返回的是一个Document类型。

      • Document用于从文档中获取根元素对象和添加一个根元素节点。返回的是Element类型。

      • Element用于操作具体的元素:包括获取/添加节点名称、内容、属性等等

      • 具体的应用核心代码:

        /*** 从本地文件作为输入流获取*/
        //1.    获取输入流
        FileInputStream fis = new FileInputStream("c://Demo1.xml");
        //2.    创建XML读取对象
        SAXReader sr = new SAXReader();
        //3.    读取并得到文档对象
        Document doc = sr.read(fis);
        //4.    通过文档获取根元素
        Element root = doc.getRootElement();
        //5.    通过根节点获取元素集合
        List<Element> es = root.elements();
        for(int i=0;i<es.size();i++){Element book = es.get(i);System.out.println(book.attributeValue("id"));System.out.println(book.elementText("name"));System.out.println(book.elementText("info"));                             System.out.println(book.element("xiang").elementText("wei"));System.out.println("-----------------------------");
        }
        /*** 从网络资源作为输入流获取*/
        //1.    获取到XML资源的输入流
        URL url = new URL("http://apis.juhe.cn/mobile/get?phone=18313935565&dtype=xml&key=9f3923e8f87f1ea50ed4ec8c39cc9253");
        URLConnection conn = url.openConnection();
        InputStream is = conn.getInputStream();
        //2.    创建一个XML读取对象
        SAXReader sr = new SAXReader();
        //3.    通过读取对象 读取XML数据,并返回文档对象
        Document doc = sr.read(is);
        
    • xPath解析更加方便:

      • 路径表达式:

        路径表达式:1. /  :  从根节点开始查找2. // :  从发起查找的节点位置 查找后代节点 常用3. .  :  查找当前节点4. .. :  查找父节点5. @  :  选择属性. 常用属性使用方式:[@属性名='值'][@属性名>'值'][@属性名<'值'][@属性名!='值'
        
      • 前面获取文档对象操作类似,下面给出核心代码:

        //1.    通过文档对象+xpath,查找所有的name节点
        List<Node> names = doc.selectNodes("//book[@id='1001']//name");
        for (int i=0;i<names.size();i++){System.out.println(names.get(i).getName());System.out.println(names.get(i).getText());
        }
        //2.    通过文档对象+xpath,查找第一个name节点
        Node n = doc.selectSingleNode("//book[@id='1002']//name");
        System.out.println(n.getName()+":"+n.getText());
        
  • Java利用文档对象生成XML(熟悉)

    • 需要借助文档帮助器这个类来创建空的文档对象

    • 有了文档对象,然后操作根节点,然后丰富子节点,这部分操作和解析类似,调用API即可。

    • 最后需要把文档对象写入到文件输出流中,因此需要先创建一个文件输出流,并利用XMLWriter类写入文档对象到文件中。

    • 核心代码如下:

      //1.    通过文档帮助器,创建一个文档对象
      Document doc = DocumentHelper.createDocument();
      //2.    给文档添加第一个节点(根节点)
      Element books = doc.addElement("books");
      //3.    通过根节点, 丰富子节点 这里忽略
      //4.    创建一个文件输出流
      FileOutputStream fos = new FileOutputStream("c://books.xml");
      //5.    将输出流转换为XML输出流
      XMLWriter xw = new XMLWriter(fos);
      //6.    写出文档
      xw.write(doc);
      //7.    释放资源
      xw.close();
      
  • XStreamJava对象生成XML(了解)

    • 最终生成的是一个字符串,核心代码如下:

      Person p = new Person();
      p.setName("张三");
      p.setAge(18);
      //XStream使用
      //1、创建XStream对象
      XStream x = new XStream();
      //2、修改某个类型生成的节点 (可选的,默认为包名.类名)
      x.alias("person",Person.class);
      //3、传入对象,开始生成
      String xml = x.toXML(p);
      System.out.println(xml);
      

JSON

  • JSON: JavaScript Object Notation JS对象简谱 , 是一种轻量级的数据交换格式.

  • 一个对象, 由一个大括号表示:

    • 括号中 描述对象的属性。通过键值对来描述对象的属性(可以理解为, 大括号中, 包含的是一个个的键值对)

    • 格式注意事项:

      • 键与值之间使用冒号连接, 多个键值对之间使用逗号分隔.

      • 键值对的使用引号引住 (通常Java解析时, 键不使用引号会报错. 而JS能正确解析.)

      • 键值对的值, 可以是JS中的任意类型的数据,考虑到其他语言兼容,常使用的有布尔类型、数字类型、字符串类型。

      • 注意键值对中的值可以继续是一个对象或者一个数组。

      • 举例说明:

        {"name":"forwardxiang","age":18,"friends":["张三","李四","王二","麻子",{"name":"我就是我","info":"不一样的烟火"}],"history":{"school":"大学",}}
        
    • 根据使用的编程语言去查询对应的JSON库,例如C/C++语言常用的最简单的cJSON库Java使用的谷歌的Gson和阿里的FastJson,可以从GitHub中下载最新的包。由于Java官方没有内置相关库,使用其他库可能带来漏洞危险。

  • Java对象和JSON字符串互转

    • 经过实际调试发现:GsonFastJson库在JSON字符串转Java对象有所区别,FastJson库在使用JSON.parseObject进行解析时会报JSONException: create instance error错误,它要求指定要转换的类是public的。

    • Gson常用API:

      /**
      * Java对象转JSON字符串
      */
      Book b = new Book("100","金苹果","种植苹果真辛苦");
      String s = new Gson().toJson(b);
      System.out.println(s);
      /**
      * JSON字符串转Java对象
      */
      Book a = new Gson().fromJson(s, Book.class);
      System.out.println(a.getId());
      
    • FastJson常用API:

      /**
      * Java对象转JSON字符串
      */
      Book book = new Book("100","金苹果","种植苹果真辛苦");
      String jsons = JSON.toJSONString(book);
      System.out.println(jsons);
      /**
      * JSON字符串转Java对象
      */
      Book b = JSON.parseObject(jsons, Book.class);
      System.out.println(b.getId());
      
    • JSON字符串Java对象时,可以指定转换的类型,因此可以指定转换为HashMap集合,然后通过键名去获取各个键值。

    • JSON数组Java中对应一个ArrayList集合,FastJson中还特意提供了JSON.parseArray方法用于单独解析数组。

我的疑问

  • FastJson库在使用JSON.parseObject进行解析时会报JSONException: create instance error错误原因是什么?

    • 这个问题主要是因为Java内部类和嵌套类的实现机制造成的,首先按照Java编程思想的说法,静态的内部类叫做嵌套类,那么两者有什么区别呢?一般的内部类虽然在源代码中没有写,但是编译后会看到里面多了一个指向外部类的引用,如果使用内部类进行json序列化,会因为找不到它的外部类而报异常,而嵌套类因为是静态的,里面没有默认的外部类的引用,即使没有外部类的对象能够使用,因此在json转换的时候不会报错。

XML与JSON 及其对应的Java包 Gson FastJson相关推荐

  1. kryo java_优化Java序列化– Java,XML,JSON,Kryo,POF

    kryo java 也许我很天真,但是我一直认为Java序列化肯定是将Java对象序列化为二进制形式的最快,最有效的方法. 毕竟Java是第7个主要发行版,所以这不是新技术,而且由于每个JDK似乎都比 ...

  2. 优化Java序列化– Java,XML,JSON,Kryo,POF

    也许我很天真,但是我一直认为Java序列化肯定是将Java对象序列化为二进制形式的最快,最有效的方法. 毕竟Java是第7个主要发行版,所以这不是新技术,并且由于每个JDK似乎都比上一个快,因此我错误 ...

  3. saxon 使用_Java XML和JSON:Java SE的文档处理,第1部分:SAXON和Jackson

    saxon 使用 XML和JSON对我来说很重要,我感谢Apress让我写了一整本有关它们的书. 在本文中,我将简要介绍新书的第二版Java XML和JSON . 如果有足够的空间,我还将展示两个有用 ...

  4. json:JSONObject包的具体使用(JSONObject-lib包是一个beans,collections,maps,java arrays和xml和JSON互相转换的包)...

    1.JSONObject介绍 JSONObject-lib包是一个beans,collections,maps,java arrays和xml和JSON互相转换的包. 2.下载jar包 http:// ...

  5. JAVA序列化标准格式(XML、JSON)

    (一) 序列化:将java对象转换为字节序列的过程叫做序列化 反序列化:将字节对象转换为java对象的过程叫做反序列化 通常情况下,序列化有两种用途: 1) 把对象的字节序列永久的保存在硬盘中 2) ...

  6. JAVA工具方法 —— JSON转XML 和 XML转JSON

    2019独角兽企业重金招聘Python工程师标准>>> 这阵子一直在做一个三方支付,数据传递用的都是xml 但是在项目里都是用的json,没办法 研究了下json和xml互转的方法 ...

  7. Java学习(第十二天)XML和JSON

    XML和json XML:可扩展标记语言(eXtensible Markup Language) 特性: 1.xml具有平台无关性,是一门独立的标记语言 2.xml具有自主描述性 学习xml的理由: ...

  8. Java学习-11 XML与JSON

    Java学习-11 XML与JSON 1.XML 1.1.简介 可扩展标记语言(eXtensible Markup Language). 特性:1. xml具有平台无关性, 是一门独立的标记语言.2. ...

  9. Java如何xml转json字符串_xml字符串转json字符串

    XML字符串转JSON字符串网上的方法很多,这里主要推荐两种: 1.使用org.json包 jar地址:http://mvnrepository.com/artifact/org.json/json ...

最新文章

  1. windows7 端口查看以及杀死进程释放端口
  2. python给一列数据增加前缀_python自制工具----给文件添加前后缀。
  3. MaxCompute 多行数据合并为一行数据
  4. 精通mysql_《深入精通Mysql(五)》实战:Mysql实现主从复制
  5. MSRA的Transformer跨界超越CNN,还解决了计算复杂度难题
  6. 小程序工程化实践(上篇)-- 手把手教你撸一个小程序 webpack 插件,一个例子带你熟悉 webpack 工作流程...
  7. 在博客中如何让code具有比较易读的格式
  8. 美肤磨皮算法OpenCV3实现
  9. (SQL语句)按指定时间段分组统计
  10. java 开发人员工具_Java开发人员应该知道的7种新工具
  11. 做技术知道了哪些事情代表自己成熟了?
  12. 垃圾回收 | Java垃圾回收,这杯咖啡,不仅好喝,而且实用!
  13. node-gyp 出错
  14. 算法图解 各部分回忆
  15. sql 判断分钟是偶数数据_SQL注入数据库类型判断
  16. 简述static关键字、void与void *(void指针)、函数指针
  17. 删除root 家目录,及恢复方法
  18. Python人脸识别之——创建csv文件 create_csv.py 代码 Python3.7
  19. DICOM获取worklist患者列表抓包分析
  20. 深度学习花书+机器学习西瓜书电子版我找到了

热门文章

  1. 深蓝学院-视觉SLAM课程-第3讲笔记-李群和李代数
  2. 天空卫士C++ 一面(技术面、61min)
  3. ansible 修改文件变量_ansible学习心得
  4. Java实现 LeetCode 385 迷你语法分析器
  5. Origin软件的快捷键汇总及工具栏快速指引
  6. 【安信可PB-01/02模组专题③】ESP32-G WIFI蓝牙网关与PB02模组开发进行组网通讯
  7. 跨界储能领域 金冠股份签订7000万锂电池储能系统销售大单
  8. C 语言初学——一起分享、共同学习。
  9. 可解释的对抗训练网络模型:Interpreting Adversarially Trained Convolutional Neural Networks-ICML 2019
  10. 图数据库Neo4j学习笔记系列