Java从入门到实战总结-3.7、XML和JSON

2023-10-27

Java从入门到实战总结-3.7、XML和JSON


1. 前言

这里分享两个故事来说明数据规则的重要性。

其一就是目前微信公众平台的故事:今天是 20xx 年 x 月 x 日,你作为优秀开发者被邀请参与 《微信开发者技术沙龙》。李老师是给你留下印象最深的受邀嘉宾,他属于鹅肠微信公众平台官方人员,他的分享对你触动很大。他分享了公众平台接口数据格式 XML 与 JSON混乱的缘由。

在鹅肠微信公众平台设计早期,因为开发团队是从鹅肠其他团队凑的。内部不同的子团队开发规范很不一致。很多老团队喜欢使用 XML 格式传输数据(少数,点击查看(https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_standard_messages.html)),很多新人团队过来的成员喜欢使用 JSON 作为传输格式(多
数,点击查看(https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Service_Center_messages.html))。为了团队的稳定,当时并没有对格式进行特殊的规则定制,导致现在很多开发者对此怨声载道。

因为平台已经有了百万的开发者,再更改操作规范会导致大量生态问题的发生,所以到目前问题依旧存在,难以修缮。

你在参与这次技术沙龙之前,对数据传输的格式不太在意。李老师的分享对你触动很大,也让你明白了,开发时如果前后端没有一个合理统一的数据规则,会有大量的不必要问题发生。所以你下定决心要掌握好 JSON 和 XML 技术。

其二是我们之前公司大数据平台和数据采集设备之间通信的数据格式是自定义的格式,采用#号$等各种符号进行数据分隔,年久失修,导致项目维护人员怨声载道,每次拿到数据都要对着奇怪的数据格式文档进行"解密分析",平台侧和设备侧有事没事都拿这个数据格式说事,最后没办法才花功夫又重构了代码来解决数据格式问题。

2. XML介绍

(1). XML概述

以下来自维基百科:

可扩展标记语言(英语:Extensible Markup Language,简称:XML)是一种标记语言。标记指计算机所能理解的信息符号,通过此种标记,计算机之间可以处理包含各种信息的文章等。如何定义这些标记,既可以选择国际通用的标记语言,比如HTML,也可以使用像XML这样由相关人士自由决定的标记语言,这就是语言的可扩展性。XML是从标准通用标记语言(SGML)中简化修改出来的。它主要用到的有可扩展标记语言、可扩展样式语言(XSL)、XBRL和XPath等。

(2). 用途

XML设计用来传送及携带数据信息,不用来表现或展示数据,HTML则用来表现数据,所以XML用途的焦点是它说明数据是什么,以及携带数据信息。

  • 富文档(Rich Documents)- 自定文件描述并使其更丰富
    • 属于文件为主的XML技术应用
    • 标记是用来定义一份资料应该如何呈现
  • 元数据(Metadata)- 描述其它文件或网络资讯
    • 属于资料为主的XML技术应用
    • 标记是用来说明一份资料的意义
  • 配置文档(Configuration Files)- 描述软件设置的参数

(3). 处理器与应用

处理器(Processor)与应用(application)
XML处理器(Processor,也称作XML parser)分析标记语言并传递结构化信息给应用(application)。

(4). 标记(Markup)与内容(content)

XML文档的字符分为标记(Markup)与内容(content)两类。标记通常以<开头,以>结尾;或者以字符& 开头,以;结尾。不是标记的字符就是内容。但是CDATA部分,分解符号<![CDATA[]]>是标记,二者之间的文本为内容。 最外界的空白符是标记。

(5). 标签(Tag)

一个tag属于标记结构,以<开头,以>结尾。Tag名字是大小写敏感,不能包括任何字符 !"#$%&’()*+,/;<=>?@[]^`{|}~, 也不能有空格符, 不能以"-“或”."或数字开始。可分为三类:

  • start-tag,如<section>;
  • end-tag,如</section>;
  • empty-element tag,如<line-break />.

(6). 元素(Element)

元素是文档逻辑组成,或者在start-tag与匹配的end-tag之间,或者仅作为一个empty-element tag。例如:<greeting>Hello, world!</greeting>. 另一个例子是: <line-break />.

单个根(root)元素包含所有的其他元素。

(7). 属性(Attribute)

属性是一种标记结构,在start-tag或empty-element tag内部的"名字-值对"。例如:<img src="madonna.jpg" alt="Madonna" />。每个元素中,一个属性最多出现一次,一个属性只能有一个值。

如果属性有多个值,这需要采取XML协议以外的方式来表示,如采用逗号或分号间隔,对于CSS类或标识符的名字可用空格来分隔。

(8). XML 声明(declaration)

XML文档如果以XML declaration开始,则表述了文档的一些信息。如<?xml version="1.0" encoding="UTF-8"?>.

例:
XML定义结构、存储信息、传送信息。下例为小张发送给大元的便条,存储为XML。

<?xml version="1.0"?>
  <小纸条>
    <收件人>大元</收件人>
    <發件人>小張</發件人>
    <主題>問候</主題>
    <具體內容>早啊,飯吃了沒? </具體內容>
  </小纸条>

这XML文档仅是纯粹的信息标签,这些标签意义的展开依赖于应用它的程序。

(9). 结构

每个XML文档都由XML声明开始,在前面的代码中的第一行就是XML声明,<?xml version="1.0"?>。这一行代码会告诉解析器或浏览器这个文件应该按照XML规则进行解析。

但是,根元素到底叫<小纸条>还是<小便条>,则是由文档类型定义(DTD)或XML纲要(XML Schema)定义的。如果DTD规定根元素必须叫<小便条>,那么若写作<小纸条>就不符合要求。这种不符合DTD或XML纲要的要求的XML文档,被称作不合法的XML,反之则是合法的XML。

XML文件的第二行并不一定要包含文档元素;如果有注释或者其他内容,文档元素可以迟些出现。

最常见的PI(processing instruction,像XML序言, 却是不同类型的语法)是用来指定XML文件的样式表, 这个PI一般会直接放在XML序言之后,通常由Web浏览器使用,来将XML数据以特殊的样式显示出来。

XML的结构有一个缺陷,那就是不支持分帧(framing)。当多条XML消息在TCP上传输的时候,无法基于XML协议来确定一条XML消息是否已经结束。

3. Java处理XML

(1). Java解析XML的方式

Java中有几种XML解析方式?分别是什么?有什么样的优缺点?

    1. SAX解析

解析方式是事件驱动机制!

SAX解析器,逐行读取XML文件解析,每当解析到一个标签的开始/结束/内容/属性时,触发事件.我们可以编写程序在这些事件发生时, 进行相应的处理.

优点:
1.分析能够立即开始,而不是等待所有的数据被处理
2.逐行加载,节省内存.
3.有助于解析大于系统内存的文档有时不必解析整个文档,它可以在某个条件得到满足时停止解析.
缺点:
1.单向解析,无法定位文档层次,无法同时访问同一文档的不同部分数据(因为逐 行解析, 当解析第n行是, 第n-1行已经被释放了, 无法在进行操作了).
2.无法得知事件发生时元素的层次, 只能自己维护节点的父/子关系.
3.只读解析方式, 无法修改XML文档的内容.

    1. DOM解析

是用与平台和语言无关的方式表示XML文档的官方W3C标准,分析该结构通常需要加载整个 文档和内存中建立文档树模型.程序员可以通过操作文档树, 来完成数据的获取 修改 删除等.

优点:
1.文档在内存中加载, 允许对数据和结构做出更改.
2.访问是双向的,可以在任何时候在树中双向解析数据。
缺点:
文档全部加载在内存中 , 消耗资源大.

    1. JDOM解析

目的是成为Java特定文档模型,它简化与XML的交互并且比使用DOM实现更快。由于是第一 个Java特定模型,JDOM一直得到大力推广和促进。 JDOM文档声明其目的是"使用20%(或更少)的精力解决80%(或更多)Java/XML问题" (根据学习曲线假定为20%)

优点:
1.使用具体类而不是接口,简化了DOM的API。
2.大量使用了Java集合类,方便了Java开发人员。
缺点:
1.没有较好的灵活性。
2.性能不是那么优异。

    1. DOM4J解析(掌握)

它是JDOM的一种智能分支。它合并了许多超出基本XML文档表示的功能,包括集成的XPath 支持、XML Schema支持以及用于大文档或流化文档的基于事件的处理。它还提供了构建文档表示的选项, DOM4J是一个非常优秀的Java XML API,具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件。如今你可以看到越来越多的Java软件都在使用DOM4J来读写XML。

目前许多开源项目中大量采用DOM4J , 例如:Hibernate

(2). DOM4J解析XML

    1. 引入jar文件 dom4j.jar
    1. 创建一个指向XML文件的输入流 FileInputStream fis = new FileInputStream(“xml文件的地址”);
    1. 创建一个XML读取工具对象 SAXReader sr = new SAXReader();
    1. 使用读取工具对象, 读取XML文档的输入流 , 并得到文档对象 Document doc = sr.read(fis);
    1. 通过文档对象, 获取XML文档中的根元素对象 Element root = doc.getRootElement();

文档对象Document

指的是加载到内存的 整个XML文档.

常用方法:

  1. 通过文档对象, 获取XML文档中的根元素对象 Element root = doc.getRootElement();

  2. 添加根节点 Element root = doc.addElement(“根节点名称”);

元素对象 Element:

指的是XML文档中的单个节点.

常用方法:

  1. 获取节点名称 String getName();

  2. 获取节点内容 String getText();

  3. 设置节点内容 String setText();

  4. 根据子节点的名称 , 获取匹配名称的第一个子节点对象. Element element(String 子节点名称);

  5. 获取所有的子节点对象 List<Element> elements();

  6. 获取节点的属性值 String attributeValue(String 属性名称);

  7. 获取子节点的内容 String elementText(String 子节点名称);

  8. 添加子节点 Element addElement(String 子节点名称);

  9. 添加属性void addAttribute(String 属性名,String 属性值);

(3). 导入jar包

JDK竟然不提供xml和json相关的包,令人匪夷所思,所以xml和json的处理需要导入外部jar包。

dom4j官网:https://dom4j.github.io/

可以导入到默认位置,也可以自建lib文件夹导入,一般我们为了方便确认导入的lib会在src同级目录下创建lib文件夹,然后复制进来jar包,之后再项目中导入jar包,再将导入的包应用于src模块。

下载jar包后选择文件->项目结构->库之后导入java来选择jar包导入:

在这里插入图片描述

这里可以直接添加该lib依赖到我们的模块,如果不小心取消了还可以选择模块,然后在模块中重新添加依赖:

在这里插入图片描述

对于这里我们整个demo1模块都可以使用添加进来的dm4j依赖库了。

这里我们导入了三个jar包,但是我们导入库的时候默认使用了第一个名字作为库的名字,所以这里显示了dom4j-1.6.1,实际上我们导入了三个xml相关的jar包,如果怕误解可以更改以下库的名字,我这里暂时就不改了:

在这里插入图片描述

(4). xml文件解析

我们通过一个实际的xml文件来示例以下使用dom4j解析xml文件。

xml文件内容:

<?xml version="1.0" encoding="UTF-8"?>
<books>
  <book id="1001">
    <name>金苹果</name>
    <info>锄禾日当午,苹果很辛苦</info>
  </book>
  <book id="1002">
    <name>银苹果</name>
    <info>锄禾日当午,苹果很辛苦</info>
  </book>
</books>

然后按照我们上面的几步进行xml文件读取:

package com.xiaoyaoyou.day13;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.List;

public class XMLDom4jTest {
    public static void main(String[] args) throws FileNotFoundException, DocumentException {
        //1. 获取输入流
        FileInputStream fileInputStream = new FileInputStream("Demo1.xml");
        //2. 创建xml读取对象
        SAXReader saxReader = new SAXReader();
        //3. 读取并获取文档对象
        Document document = saxReader.read(fileInputStream);
        //4. 通过文档获取根元素
        Element root = document.getRootElement();
        //5. 开始解析元素
        System.out.println(root.getName());

        //获取元素或属性内容
        List<Element> elementList = root.elements();
        for(int i = 0; i < elementList.size(); i++) {
            Element book = elementList.get(i);
            System.out.println(book.attributeValue("id"));
            System.out.println(book.elementText("name"));
            System.out.println(book.elementText("info"));
            System.out.println("-----------------------");
        }
    }
}

结果:

books
1001
金苹果
锄禾日当午,苹果很辛苦
-----------------------
1002
银苹果
锄禾日当午,苹果很辛苦
-----------------------

这里有坑点需要注意:运行时报错:

Exception in thread "main" org.dom4j.DocumentException: 1 字节的 UTF-8 序列的字节 1 无效。 Nested exception: 1 字节的 UTF-8 序列的字节 1 无效。

这个是文档的编码和xml的编码不一致导致的,很可能是文档是GBK格式创建的,但是解析xml时我们又指定使用UTF-8,那么我们将其编码修改一致即可,要么将xml的编码修改为GBK(和文档编码保持一致,使用notepad++打开看以下右下角的编码),要么就使用编辑器转换一下文档的编码为UTF-8即可。

(5). 网络数据xml解析

我们使用聚合数据网站的api来获取网络xml数据流,然后解析网络xml数据流,这个也是目前微信公众号等一些网站可能提供的api接口返回的数据流。

https://www.juhe.cn/docs

可以选择一些免费的api用来测试,比如我们这里使用免费的收集归属地查询使用任意一个手机号码做归属地查询。

package com.xiaoyaoyou.day13;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

public class XMLDom4jTest2 {
    public static void main(String[] args) throws IOException, DocumentException {
        String phone = "18516955565";
        //1. 获取到XML资源的输入流
        URL url = new URL("http://apis.juhe.cn/mobile/get?phone="+phone+"&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);
        //4. 获取根节点
        Element root = doc.getRootElement();
        //5. 解析内容
        String code = root.elementText("resultcode");
        if("200".equals(code)) {
            Element result = root.element("result");
            String province = result.elementText("province");
            String city = result.elementText("city");
            if(province.equals(city)) {
                System.out.println("手机号码归属地为:"+city);
            }else{
                System.out.println("手机号码归属地为:"+province+" "+city);
            }
        }else{
            System.out.println("请输入正确的手机号码");
        }
    }
}

结果:

手机号码归属地为:北京

(6). 通过XPATH解析xml

即通过路径快速的查找一个或一组元素。

路径表达式:

  • / : 从根节点开始查找
  • // : 从发起查找的节点位置 查找后代节点
  • . : 查找当前节点
  • … : 查找父节点
  • @ : 选择属性

属性使用方式:
[@属性名=‘值’]
[@属性名>‘值’]
[@属性名<‘值’]
[@属性名!=‘值’]

<?xml version="1.0" encoding="GBK"?>
<books>
  <book id="1001">
    <name>金苹果</name>
    <info>锄禾日当午,苹果很辛苦</info>
  </book>
  <book id="1002">
    <name>银苹果</name>
    <info>锄禾日当午,苹果很辛苦</info>
  </book>
</books>

books: 路径: //book[@id=‘1001’]//name

books
  book id=1001
    name
    info
  book id=1002
    name
    info

示例:

package com.xiaoyaoyou.day13;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.List;

public class XMLDom4jTest3 {
    public static void main(String[] args) throws FileNotFoundException, DocumentException {
        //1. 获取输入流
        FileInputStream fileInputStream = new FileInputStream("Demo1.xml");
        //2. 创建xml读取对象
        SAXReader saxReader = new SAXReader();
        //3. 读取并获取文档对象
        Document document = saxReader.read(fileInputStream);
        //4. 通过文档获取根元素
//        Element root = document.getRootElement();
        //5. 开始解析元素
//        System.out.println(root.getName());

        //获取元素或属性内容
//        for(int i = 0; i < elementList.size(); i++) {
//            Element book = elementList.get(i);
//            System.out.println(book.attributeValue("id"));
//            System.out.println(book.elementText("name"));
//            System.out.println(book.elementText("info"));
//            System.out.println("-----------------------");
//        }

        //直接通过XPATH找位置获取内容
        Node node = document.selectSingleNode("//book[@id='1001']//name");
        System.out.println(node.getName() + ":" + node.getText());
    }
}

结果:

name:金苹果

同理,网络数据经过xml解析后也可以这样操作,一般我们可以通过vscode或者网上的网站进行xml解析获取路径来快速定位XPATH后进行相关内容获取。

<root>
    <resultcode>200</resultcode>
    <reason>Return Successd!</reason>
    <result>
        <province>上海</province>
        <city>上海</city>
        <areacode>021</areacode>
        <zip>200000</zip>
        <company>联通</company>
        <card/>
    </result>
    <error_code>0</error_code>
</root>

我们直接获取运营商:

package com.xiaoyaoyou.day13;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

public class XMLDom4jTest4 {
    public static void main(String[] args) throws IOException, DocumentException {
        String phone = "18516755567";
        //1. 获取到XML资源的输入流
        URL url = new URL("http://apis.juhe.cn/mobile/get?phone="+phone+"&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);
        //4. 获取根节点
//        Element root = doc.getRootElement();
        //5. 解析内容
//        String code = root.elementText("resultcode");
//        if("200".equals(code)) {
//            Element result = root.element("result");
//            String province = result.elementText("province");
//            String city = result.elementText("city");
//            if(province.equals(city)) {
//                System.out.println("手机号码归属地为:"+city);
//            }else{
//                System.out.println("手机号码归属地为:"+province+" "+city);
//            }
//        }else{
//            System.out.println("请输入正确的手机号码");
//        }
        Node node = doc.selectSingleNode("//company");
        System.out.println("运营商:"+node.getText());
        is.close();
    }
}

结果:

运营商:联通

(7). XML生成

步骤:

    1. 通过文档帮助器 (DocumentHelper) , 创建空的文档对象 Document doc = DocumentHelper.createDocument();
    1. 通过文档对象, 向其中添加根节点 Element root = doc.addElement(“根节点名称”);
    1. 通过根节点对象root , 丰富我们的子节点 Element e = root.addElement(“元素名称”);
    1. 创建一个文件输出流 ,用于存储XML文件 FileOutputStream fos = new FileOutputStream(“要存储的位置”);
    1. 将文件输出流, 转换为XML文档输出流 XMLWriter xw = new XMLWriter(fos);
    1. 写出文档xw.write(doc);
    1. 释放资源xw.close();
package com.xiaoyaoyou.day13;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

public class XMLDom4jWriteXMLTest {
    public static void main(String[] args) throws IOException, DocumentException {
        //1. 通过文档帮助器,创建一个文档对象
        Document document = DocumentHelper.createDocument();
        //2. 给文档添加一个根节点
        Element books = document.addElement("books");
        //3. 通过根节点,丰富子节点
        for(int i = 0; i < 10; i++) {
            Element book = books.addElement("book");
            Element name = book.addElement("name");
            name.setText(i+"种苹果");
            Element info = book.addElement("info");
            info.setText(i+"种苹果的故事");
            book.addAttribute("id", 100+i+"");
        }
        //4. 创建一个文件输出流
        FileOutputStream fileOutputStream = new FileOutputStream("books.xml");
        //5. 将输出流转换为xml输出流
        XMLWriter xmlWriter = new XMLWriter(fileOutputStream);
        //6. 写出文档
        xmlWriter.write(document);
        //7. 释放资源
        xmlWriter.close();
        System.out.println("执行完成");
    }
}

结果:

在这里插入图片描述
此外,还可以将对象直接转换为xml内容,相关接口使用查询一下官网的示例探索一下吧。

4. JSON介绍

(1). 概述

JSON(JavaScript Object Notation,JavaScript对象表示法,读作/ˈdʒeɪsən/)是一种由道格拉斯·克罗克福特构想和设计、轻量级的资料交换语言,该语言以易于让人阅读的文字为基础,用来传输由属性值或者序列性的值组成的数据对象。尽管JSON是JavaScript的一个子集,但JSON是独立于语言的文本格式,并且采用了类似于C语言家族的一些习惯。

JSON 数据格式与语言无关。即便它源自JavaScript,但目前很多编程语言都支持 JSON 格式数据的生成和解析。JSON 的官方 MIME 类型是 application/json,文件扩展名是 .json。

(2). 应用领域

  • WEB开发
    JSON最开始被广泛的应用于WEB应用的开发。不过目前JSON使用在JavaScript、Java、Node.js应用的情况比较多,PHP、C#等开发的WEB应用主要还是使用XML。

  • NoSQL数据库
    相对于传统的关系型数据库,一些基于文档存储的NoSQL非关系型数据库选择JSON作为其数据存储格式,比较出名的产品有:MongoDB、CouchDB、RavenDB等。

(3). 示例

{
     "firstName": "John",
     "lastName": "Smith",
     "sex": "male",
     "age": 25,
     "address": 
     {
         "streetAddress": "21 2nd Street",
         "city": "New York",
         "state": "NY",
         "postalCode": "10021"
     },
     "phoneNumber": 
     [
         {
           "type": "home",
           "number": "212 555-1234"
         },
         {
           "type": "fax",
           "number": "646 555-4567"
         }
     ]
 }

(4). 与XML的比较

JSON与XML最大的不同在于XML是一个完整的标记语言,而JSON不是。这使得XML在程序判读上需要比较多的功夫。主要的原因在于XML的设计理念与JSON不同。XML利用标记语言的特性提供了绝佳的延展性(如XPath),在数据存储,扩展及高级检索方面具备对JSON的优势,而JSON则由于比XML更加小巧,以及浏览器的内建快速解析支持,使得其更适用于网络数据传输领域。

(5). 格式化工具

和XML一样,目前都比较推荐VSCode进行格式化:

在这里插入图片描述

5. Java处理JSON

这里也同样需要使用外部包,目前使用较多的是gson和fastjson、jackson(导入jar包和xml类似,jdk目前同样不提供接口):

https://github.com/google/gson

https://github.com/alibaba/fastjson

https://github.com/FasterXML/jackson

包括:

  • 将对象转换为JSON字符串
  • 将JSON字符串转换为对象

我们以gson为例做简单的示例:

package com.xiaoyaoyou.day13;

import com.google.gson.Gson;

import java.util.Objects;

public class gsonTest {
    public static void main(String[] args) {
        //1. 创建Gson对象
        Gson gSon = new Gson();
        //2. 转换
        Book book = new Book("100", "金苹果", "种植苹果真辛苦");
        String s = gSon.toJson(book);
        System.out.println(s);
    }
}

class Book {
    private String id;
    private String name;
    private String info;

    public Book(String id, String name, String info) {
        this.id = id;
        this.name = name;
        this.info = info;
    }

    public Book() {
    }

    @Override
    public String toString() {
        return "Book{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", info='" + info + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Book book = (Book) o;
        return Objects.equals(id, book.id) && Objects.equals(name, book.name) && Objects.equals(info, book.info);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name, info);
    }

    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 String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }
}

结果:

{"id":"100","name":"金苹果","info":"种植苹果真辛苦"}
package com.xiaoyaoyou.day13;

import com.google.gson.Gson;

import java.util.Objects;

public class gsonTest {
    public static void main(String[] args) {
        //1. 创建Gson对象
        Gson gSon = new Gson();
        //2. 转换
        Book book = new Book("100", "金苹果", "种植苹果真辛苦");
        String s = gSon.toJson(book);
        System.out.println(s);

        Book book1 = gSon.fromJson(s, Book.class);
        System.out.println(book1.getName());
    }
}

class Book {
    private String id;
    private String name;
    private String info;

    public Book(String id, String name, String info) {
        this.id = id;
        this.name = name;
        this.info = info;
    }

    public Book() {
    }

    @Override
    public String toString() {
        return "Book{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", info='" + info + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Book book = (Book) o;
        return Objects.equals(id, book.id) && Objects.equals(name, book.name) && Objects.equals(info, book.info);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name, info);
    }

    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 String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }
}

结果:

{"id":"100","name":"金苹果","info":"种植苹果真辛苦"}
金苹果

至于其它的一些库等项目中有需求再了解一下相关api如何使用。

6、最后

总的来说,json用的会多一些,但是xml也有很多场景需要使用,所以都需要掌握。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java从入门到实战总结-3.7、XML和JSON 的相关文章

  • 在记录活动中使用 readConfiguration 方法

    为了在小型 Java 桌面应用程序中使用日志记录 我试图深入了解一些方法的操作 我使用一个非常愚蠢的小Java程序来测试它们 特别是 在测试 LogManager readConfiguration 方法的行为时 我发现了一些奇怪的事情 在
  • 限制执行第三方软件的线程的权限

    我正在开发一个基于 Eclipse 的应用程序 能够执行第三方组件 不是 eclipse plugin 每个组件都有一个列出权限 以及相应动机 的自定义描述符 这样最终用户可以决定是否执行它 组件在单独的线程中执行 如何根据描述符限制这些线
  • 如何选择主题与队列

    当我们设计应用程序时如何选择Topic Queue类型实现 我知道 a 如果有多个消费者使用该消息 则使用 Topicb 如果只有一个消费者则使用Queue 请提供更多需要考虑的点 比如并发 消息持久化 负载均衡等等 Thanks Rw 如
  • 为什么这个 Java 静态字段为空?

    public class StaticTest private static String a private static String b this is a public static void main String args a
  • 有效 JSON 上的 Firefox JSON“格式不正确”错误

    我在 Firefox 中收到以下错误消息 Error not well formed Source File http school courses booking add php 1287657494723 Line 1 Column 1
  • 如何处理 FOR XML PATH/AUTO 中的空白值 - SQL Server?

    有没有人对这种 SQL Server 行为有任何见解或遇到过 当空白值转换为数据类型时 char 或具有 的列char 作为数据类型 处理使用For XML PATH 它返回 XML 结果 20 空格的特殊字符编码 当相同的空白值转换为va
  • 单击按钮时更改照片

    import javax swing Icon import javax swing ImageIcon public class Stage1 extends javax swing JFrame int score 0 int iter
  • 在java中将HTML转换为RTF?

    我需要将 HTML 转换为 RTF 我正在使用以下代码 private static String convertToRTF String htmlStr OutputStream os new ByteArrayOutputStream
  • Java(正则表达式)-获取句子中的所有单词

    我需要将 java 字符串拆分为单词数组 假设该字符串是 Hi I need to split this string into a serie s of words 目前我正在尝试使用这个String strs str split w 但
  • JFreeChart 更改现有条形图中的数据

    我想循环更改条形图数据 但我不知道该怎么做 我的代码 DefaultCategoryDataset barChartData new DefaultCategoryDataset barChartData setValue 0 Values
  • 在 json 对象中执行 javascript 代码?

    有远吗 所以像这样 key1 val1 key2 val2 some code document getElementById someid innerHTML test 那么 some code 会在没有任何用户干预的情况下执行吗 No
  • 如何从 ByteBuffer 转换为 Integer 和 String?

    我转换了一个int使用 ByteBuffer 的字节数组putInt 方法 我该如何做相反的事情 那么将这些字节转换为 int 吗 此外 我使用 String 的将字符串转换为字节数组getBytes 方法 我如何将其反过来转换 这byte
  • 获取 Spring Boot 中当前活动数据源的引用

    我想通过实现数据库数据初始化DataSourceInitializer 我将这些方法放在我的 Spring Boot 主方法下面 但似乎它根本没有被执行 我尝试故意删除字符只是为了触发一个错误来确认执行 什么也没有发生 Configurat
  • Java 多态性中的字段如何工作? [复制]

    这个问题在这里已经有答案了 我正在读书面试问题 http javabypatel blogspot in 2016 04 java interview questions html关于java 发现了很好的例子 但感到困惑 因为没有很好 更
  • 为什么 (Oracle) JVM 对内存使用有固定上限 (-Xmx)?

    本着提问的精神Java 为什么存在 MaxPermSize https stackoverflow com questions 3356005 java why does maxpermsize exist 我想问一下为什么Oracle J
  • JRuby调用了错误的方法

    我在调用 Java 方法时遇到了一个奇怪的问题JRuby http en wikipedia org wiki JRuby 在我的 Java 类中 这些方法定义了两次 看来 JRuby 调用了错误的方法 所以我尝试使用java method
  • 在java中访问dll方法

    我正在尝试访问java中用c 编写的dll方法 从下面的代码我试图构建已成功生成的 dll using System using Microsoft Win32 namespace CyberoamWinHelper public clas
  • Java:当计时器处于活动状态时,JSplitPane 将顶部面板的内容复制到底部面板

    所以我有一个 JSplitPane 和两个 JPanel 一个在顶部 一个在底部 在这两个面板中 我重写了paintComponent方法并添加了我自己的图形 在底部面板中 我想添加动画 当面板不重新绘制时 这很好 但是一旦计时器 java
  • java中的“main”可以返回字符串吗?

    java中的public static void main String args 是否有可能返回String代替void 如果是 怎么办 public static String main String args 代替 public st
  • Json.net 将数字属性序列化为字符串

    我正在使用 JsonConvert SerializeObject 序列化模型对象 服务器期望所有字段都是字符串 我的模型对象具有数字属性和字符串属性 我无法向模型对象添加属性 有没有办法将所有属性值序列化为字符串 我必须只支持序列化 而不

随机推荐