【Java从头开始】第四章【3】XML和JSON

第四章 XML和JSON

1 XML

1.1 简介

可扩展标记语言(软件与软件交流时可用的语言)

特性:

  1. xml具有平台无关性,是一门独立的标记语言(不论是系统平台的不同还是语言平台的不同)
  2. xml具有自我描述性

1.2 学习XML的作用

  1. 网络数据传输(结构化传输)
  2. 数据存储
  3. 配置文件

1.3 XML的语法格式

1. XML文档的声明:<?xml version="1.0" encoding="UTF-8"?>   (展现了自我描述性)
2. 标记(元素/标签/节点)
<names>
	<name>张三</name>   //名称不能以数组和标点符号开始,不能以xml开头
</names>

3. 一个XML文档中必须有且只有一个根标记
4. 标记可以嵌套,但是不可以交叉
5. 标记的名称可以重复
6. 在开始标记中可以有n个属性,同一个标签中属性名不能重复
7. 注释:注释不能写在文档声明前面

举例:

<?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>

1.4 如何解析XML

1.4.1 SAX解析

事件驱动机制

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

优点:

  1. 分析能够立即开始,而不是等待所有数据被处理
  2. 逐行加载,节省内存,有助于解析大于徐通内存的文档
  3. 有时不必解析整个文档,可以在某个条件得到满足的时候停止解析

缺点:

  1. 单向解析,无法定位文章层次,无法同时访问同意文档的不同部分数据(因为是逐行解析,解析当前行的时候上一行已经被释放了)
  2. 无法得知事件发生时元素的层次,需要程序员自己去维护节点的父/子关系
  3. 只读解析方式,无法修改XML文档的内容
1.4.2 DOM解析

分析该结构需要加载整个文档和内存中建立文档树模型,可以通过操作文档树来完成数据的获取,修改,删除等

优点:

  1. 文档在内存中加载,允许对数据和结构做出更改
  2. 访问是双向的,可以在任何时候在树中双向解析数据

缺点:

  1. 文档全部加载在内存中,消耗资源大
1.4.3 JDOM解析

目的是成为Java特定文档模型,简化了与XML的交互,并且比使用DOM实现更快,是第一个Java特定模型,JDOM一直得到大力推广与促进

优点:

  1. 使用具体类而不是接口,简化了DOM的API
  2. 大量使用的Java的集合类,方便了Java开发人员

缺点:

  1. 没有较好的灵活性
  2. 性能不是那么优异
1.4.4 DOM4J

是JDOM的一种智能分支,解决了一些JDOM存在的问题,面向接口,因此更加灵活

示例:使用DOM4J解析本地文件:

public class Demo1 {
    public static void main(String[] args) throws IOException, DocumentException {
        //1. 创建指向XML文件的输入流
        FileInputStream fis = new FileInputStream("d://haha//xmlFiles//xmlDemo.xml");
        //2. 创建一个XML读取工具对象
        SAXReader reader = new SAXReader();
        //3. 使用读取工具对象,读取XML文件的输入流,并得到文档对象
        Document doc = reader.read(fis);
        //4. 通过文档对象,获取XML文档中的根元素对象
        Element root = doc.getRootElement();
        //5. 打印根元素对象的名称
        System.out.println(root.getName());

        //6. 逐级获取文件的内容
        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("----------------------");
        }
        fis.close();
    }
}

示例:解析网络文件的xml:

public class Demo2 {
    public static void main(String[] args) throws IOException, DocumentException {
        //接受用户输入手机号
        Scanner in = new Scanner(System.in);
        String phone = in.nextLine();
        //1. 创建一个url对象
        URL url = new URL("http://apis.juhe.cn/mobile/get?phone="+phone+"&dtype=xml&key=9f3923e8f87f1ea50ed4ec8c39cc9253");
        URLConnection conn = url.openConnection();
        //获得基于上述url的输入流
        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 (city.equals(province)){
                System.out.println("号码归属地为"+city);
            }else {
                System.out.println("号码归属地为"+province+"省"+city+"市");
            }
        }else {
            System.out.println("请输入正确的手机号码");
        }
    }
}

1.5 DOM4J-XPATH解析XML

路径表达式:

通过路径快速的查找一个或一组元素
路径表达式:
1. /:从根节点开始查找
2. //:从发起查找的节点位置 查找后面的节点
3. . :查找当前节点
4. .. :查找父节点
5. @ :选择属性:属性的使用方式:
	(1)[@attribute='value']
	(2)[@attribute>'value']
	(3)[@attribute<'value']
	(4)[@attribute!='value']
	
e.g. //book[@id='1']//name  (从当前节点查找book节点中属性id='1'的节点,得到它的name节点)	

xpath常用方法:

1. Node selectSingleNode("path name");//通过路径表达式获得节点(Node是Document和Element的父接口)
2. List<Node> selectNodes("path name");//通过路径表达式获得节点列表,同一路径下的所有节点

示例:从文件中利用xpath解析xml:

public class Demo3 {
    public static void main(String[] args) throws IOException, DocumentException {
        //1. 创建指向XML文件的输入流
        FileInputStream fis = new FileInputStream("d://haha//xmlFiles//xmlDemo.xml");
        //2. 创建一个XML读取工具对象
        SAXReader reader = new SAXReader();
        //3. 使用读取工具对象,读取XML文件的输入流,并得到文档对象
        Document doc = reader.read(fis);
        //4. 通过文档对象+xpath,查找所有的name节点
        List<Node> names = doc.selectNodes("//name");
        for (int i = 0; i < names.size(); i++) {
            System.out.println(names.get(i).getName());
            System.out.println(names.get(i).getText());
        }
    }
}

示例:从网络文件利用xpath解析xml

public class Demo4 {
    public static void main(String[] args) throws IOException, DocumentException {
        Scanner in = new Scanner(System.in);
        String phone = in.nextLine();
        //1. 创建一个url对象
        URL url = new URL("http://apis.juhe.cn/mobile/get?phone="+phone+"&dtype=xml&key=9f3923e8f87f1ea50ed4ec8c39cc9253");
        URLConnection conn = url.openConnection();
        //获得基于上述url的输入流
        InputStream is = conn.getInputStream();
        //2. 创建xml读取对象
        SAXReader sr = new SAXReader();
        //3. 通过读取对象读取xml数据,并返回文档对象
        Document doc = sr.read(is);
        //直接获得运营商(直接找到公司节点)
        Node node = doc.selectSingleNode("//company");
        System.out.println(node.getText());
    }
}

1.6 生成XML

手动添加节点输出xml

public class Demo5 {
    public static void main(String[] args) throws IOException {
        //1. 通过文档帮助器,创建一个文档对象
        Document doc = DocumentHelper.createDocument();
        //2. 给文档添加第一个根节点
        Element books = doc.addElement("books");
        //3. 通过根节点,丰富子节点
        for (int i = 0; i < 10; i++) {
            Element book = books.addElement("book");
            book.addAttribute("id",i+"");
            Element name = book.addElement("name");
            Element info = book.addElement("info");
            name.setText("清明上河图"+i);
            info.setText("描绘了宋代清明节前后的人文景观");
        }
        //4. 创建一个输出流
        FileOutputStream fos = new FileOutputStream("d://haha//xmlFiles//output.xml");
        //5. 将输出流包裹成xml输出流
        XMLWriter xr = new XMLWriter(fos);
        //6. 输出
        xr.write(doc);
        System.out.println("输出完毕");
    }
}

利用xstream直接得到对象的xml字符串

public class Demo6 {
    public static void main(String[] args) {
        Person p = new Person("张三",18);
        //1. 创建XStream都西昂
        XStream xs = new XStream();
        //2. 修改某个类型生成的节点(默认为包名.类名)
        xs.alias("Person", Person.class);
        //3. 传入对象,开始生成
        String xml = xs.toXML(p);
        System.out.println(xml);
    }
    static class Person{
        private String name;
        private int age;

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    }
}

如果没有更改别名:

image-20210112090741727

如果更改了别名:

2. JSON

简介:

JavaScript Object Notation JS对象简谱,是一种轻量级的数据交换格式
{
    "name" : "金苹果",
    "info" : "种苹果"
}

1. 一个对象由一个大括号表示,括号中描述对象的属性,通过键值对来描述对象的属性(大括号中包含的是一个个的键值对)
2. 格式:键与值之间用冒号链接,键和值用引号标注,键值对的值可以实JS中的任意类型的数据

数组格式:
[元素1,元素2 ...]

案例:
{
    "name":"格兰特船长的儿女",
    "info":"讲述了格兰特船长的相关故事"
    "author":{
                "name":"儒勒.凡尔纳"
                "birth":"1802"
			}
    "related":["海底两万里","地心游记","八十天环游地球"]
}//对象中可以嵌套对象,值中可以放数组,数组中可以继续嵌套对象

2.1 解析JSON格式

GSON工具

//将对象转化为JSON字符串
public class Demo1 {
    public static void main(String[] args) {
        //1. 创建GSON对象
        Gson gson = new Gson();
        //2. 创建book对象
        Book book = new Book("1001","The bad apple","about the hard work of planting apple");
        //3. 转化
        String s = gson.toJson(book);
        System.out.println(s);
        //{"id":"1001","name":"The bad apple","info":"about the hard work of planting apple"}
    }
}
//将JSON字符串转化为对应的对象
public class Demo2 {
    public static void main(String[] args) {
        //1. 创建GSON对象
        Gson gson = new Gson();
        //2. 转换
        String s = "{\"id\":\"1001\",\"name\":\"The bad apple\",\"info\":\"about the hard work of planting apple\"}";
        Book b = gson.fromJson(s, Book.class); //需要传入要转化的对象
        System.out.println(b.getId());
        System.out.println(b.getName());
        System.out.println(b.getInfo());//可以通过对象的get方法获得对象内部的内容
        
        //如果传入的类是HashMap,则会返回HashMap类型的对象
        HashMap map = gson.fromJson(s,HashMap.class);
        System.out.println(map.get("name"));
        
        //如果传入的JSON字符串包括了数组格式:解析出来就会变成List类型:
        // {"id":"1001","name":"The bad apple","page":["page1","page2","page3"]}
        String s1 = "{\"id\":\"1001\",\"name\":\"The bad apple\",\"page\":[\"page1\",\"page2\",\"page3\"]}";
        HashMap data = gson.fromJson(s1,HashMap.class);
        System.out.println(data.get("page"));
        System.out.println(data.get("page").getClass());//发现page键对应的值是一个List
        
        //[page1, page2, page3]
        //class java.util.ArrayList
        List list = (List) data.get("page");
        System.out.println(list.get(1));//还可以取出list中的内容
    }
}

FastJSON工具

//将Book对象转化为JSON字符串
Book book = new Book("1001","海底两万里","讲述了在海底的潜艇");
String s = JSON.toJSONString(book);
System.out.println(s);

//将JSON字符串转化为Book对象
Book book = JSON.parseObject("{\"id\":\"1001\",\"info\":\"讲述了在海底的潜艇\",\"name\":\"海底两万里\"}", Book.class);
System.out.println(book.getInfo());

//将JSON数组转化成List
String array = "[\"hello\",\"world\",\"this\",\"is\",\"clark\"]";
List<String> list = JSON.parseArray(array,String.class);//传入的类型为List中的泛型类型
System.out.println(list.get(0));
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值