XML与JSON解析

来源:互联网 发布:访问远程oracle数据库 编辑:程序博客网 时间:2024/05/17 08:00

1、什么是XML

XML(Extensible Markup Language 可扩展标记语言),XML是一个以文本来描述数据的文档。

<?xml version="1.0" encoding="UTF-8"?><people>    <person personid="E01">        <name>Tony Blair</name>        <address>10 Downing street,London,UK</address>        <tel>(061) 98765</tel>        <fax>(061) 98765</fax>        <email>blair@everywhere.com</email>    </person>    <person personid="E02">        <name>Bill Clinton</name>        <address>White House,USA</address>        <tel>(001) 6400 98765</tel>        <fax>(001) 6400 98765</fax>        <email>bill@everywhere.com</email>    </person></people>

2、XML的用途

XML技术的用途:
1、充当显示数据(以XML充当显示层)
2、存储数据(存储层)的功能
3、以XML描述数据,并在联系服务器与系统的其余部分之间传递。(传输数据一样的格式)

从某种角度讲,xml是数据封装和消息传递技术。

3、SAX解析XML

SAX是 Simple API for XML 的缩写。
SAX是读取和操作XML数据更快速、更轻量的方法。SAX允许您在读取文档时处理它,从而不必等待整个文档被存储以后才采取操作。不涉及DOM所必须的开销和概念跳跃。SAX API是一个基于事件的API,适用于处理数据流,即随着数据的流动而依次处理数据。SAX API在其解析文档时发生一定事件的时候会通知您。在您对其相应时,您不做保证的数据将会被抛弃。

SAX API 中主要有四种处理事件的接口,ContentHandler,DTDHandler,EntityResolver和 ErrorHandler。实际只要继承DefaultHandler类就可以,DefaultHandler实现了这四个事件处理器接口,然后提供了每个抽象方法的默认实现。

public class Person {    private String personid;    private String name;    private String address;    private String tel;    private String fax;    private String email;    getter and setter ...}
/** * Created by zxm on 2017/7/24. * SAX 解析的特点: * 1、基于事件驱动 * 2、顺序读取,速度快 * 3、不能任意读取节点(灵活性较差) * 4、解析时占用的内存小 * 5、SAX更适用于在性能要求更高的设备上使用(如安卓开发中) */public class PersonHandler extends DefaultHandler {    private List<Person> persons=null;    private Person p;//当前正在解析的对象    private String tag;//当前解析的标签    public List<Person> getPersons() {        return persons;    }    //开始解析文档时调用    @Override    public void startDocument() throws SAXException {        super.startDocument();        persons=new ArrayList<>();        System.out.println("开始解析文档。。。");    }    //结束解析文档时调用    @Override    public void endDocument() throws SAXException {        super.endDocument();        System.out.println("结束解析文档。。。");    }    /**     * 解析开始元素时调用     * @param uri 命名空间     * @param localName 不带前缀的标签名     * @param qName 带前缀的标签名     * @param attributes 当前标签的属性集合     * @throws SAXException     */    @Override    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {        super.startElement(uri, localName, qName, attributes);        if("person".equals(qName)){            p=new Person();            String personid=attributes.getValue("personid");            p.setPersonid(personid);        }        tag=qName;        System.out.println("startElement:"+qName);    }    /**     * 解析结束元素时调用     * @param uri     * @param localName     * @param qName     * @throws SAXException     */    @Override    public void endElement(String uri, String localName, String qName) throws SAXException {        super.endElement(uri, localName, qName);        if ("person".equals(qName)){            persons.add(p);        }        tag=null;        System.out.println("endElement:"+qName);    }    //解析文本内容时调用,包括标签之间的空格回车//char[] ch为整个文档的字符数组,start是每次的起始位置    @Override    public void characters(char[] ch, int start, int length) throws SAXException {        super.characters(ch, start, length);        if(tag!=null){            if("name".equals(tag)){                p.setName(new String(ch,start,length));            }else if("address".equals(tag)){                p.setAddress(new String(ch,start,length));            }else if("tel".equals(tag)){                p.setTel(new String(ch,start,length));            }else if("fax".equals(tag)){                p.setFax(new String(ch,start,length));            }else if("email".equals(tag)){                p.setEmail(new String(ch,start,length));            }        }    }}
    @Test    public void saxParseXMl() throws ParserConfigurationException, SAXException, IOException {        //1、创建一个SAX解析器工厂对象        SAXParserFactory  saxParserFactory=SAXParserFactory.newInstance();        //2、通过工厂创建SAX解析器        SAXParser saxParser=saxParserFactory.newSAXParser();        //3、创建一个数据解析器(需要自己编写)        PersonHandler personHandler=new PersonHandler();        //4、开始解析        InputStream is=Thread.currentThread().getContextClassLoader().getResourceAsStream("com/vince/xml/person.xml");        saxParser.parse(is,personHandler);        List<Person> persons=personHandler.getPersons();        for(Person person:persons){            System.out.println(person);        }    }

4、DOM解析XML

DOM:Document Object Model(文档对象模型)

DOM的特性:
定义一组Java接口,基于对象,与语言和平台无关将XML文档表示为树,在内存中解析和存储XML文档,允许随机访问文档的不同部分。

DOM解析XML:
DOM的优点,由于树在内存中是持久的,因此可以修改后更新。它可以在任何时候在树中上下导航,API使用起来也比较简单。

    /**     * DOM 解析MXL     * 1、基于树形结构,通过解析器一次性吧文档加载到内存中,所以会比较占用内存,可以随机访问     *    更加灵活,更适合在WEB开发中使用     */    @Test    public void domPaeseXML() throws ParserConfigurationException, IOException, SAXException {        //1.创建一个DOM解析器工厂对象        DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();        //2.通过工厂对象创建解析器对象        DocumentBuilder documentBuilder=factory.newDocumentBuilder();        //3.解析文档        InputStream is=Thread.currentThread().getContextClassLoader().getResourceAsStream("com/vince/xml/person.xml");        //此代码完成后,整个XML文档已经被加载到内存中,以树状形式存储        Document doc = documentBuilder.parse(is);        //4.从内存中读取数据        //获取节点名称为person的所有节点,返回节点集合        NodeList personNodeList=doc.getElementsByTagName("person");        ArrayList<Person> persons=new ArrayList<>();        Person p=null;        for (int i = 0; i < personNodeList.getLength(); i++) {            Node personNode=personNodeList.item(i);            p=new Person();            //获取节点的属性值            String personid=personNode.getAttributes().getNamedItem("personid").getNodeValue();            p.setPersonid(personid);            //获取当前节点的所有子节点            NodeList childNodes=personNode.getChildNodes();            for (int j = 0; j < childNodes.getLength(); j++) {                Node item=childNodes.item(j);                String nodeName=item.getNodeName();                if("name".equals(nodeName)){                    p.setName(item.getFirstChild().getNodeValue());                }else if("address".equals(nodeName)){                    p.setAddress(item.getFirstChild().getNodeValue());                }else if("tel".equals(nodeName)){                    p.setTel(item.getFirstChild().getNodeValue());                }else if("fax".equals(nodeName)){                    p.setFax(item.getFirstChild().getNodeValue());                }else if("email".equals(nodeName)){                    p.setEmail(item.getFirstChild().getNodeValue());                }            }            persons.add(p);        }        System.out.println(Arrays.toString(persons.toArray()));    }

5、JDOM解析XML

JDOM是两位著名的 Java 开发人员兼作者,Brett Mclaughlin 和 Jason Hunter 的创作成果, 2000 年初在类似于Apache协议的许可下,JDOM作为一个开放源代码项目正式开始研发了。

JDOM简化了与XML的交互并且比使用DOM实现更快,JDOM与DOM主要有两方面不同。首先,JDOM仅使用具体类而不适用接口。这在某些方面简化API,但是也限制了灵活性。第二,API大量使用了Collections类,简化了那些已经熟悉这些类的Java开发者使用。

下载地址:http://www.jdom.org/downloads/index.html

    /**     * JDOM 解析XML     *  1、与DOM类型基于树形结构。     *  2、与DOM的区别:     *   (1)第三方开源的组件     *   (2)实现使用JAVA的Collection接口     *   (3)效率比DOM更快     */    @Test    public void jdomParseXML() throws JDOMException, IOException {        //创建JDOM解析器        SAXBuilder builder=new SAXBuilder();        InputStream is=Thread.currentThread().getContextClassLoader().getResourceAsStream("com/vince/xml/person.xml");        org.jdom2.Document build=builder.build(is);        Element rootElement=build.getRootElement();        List<Person> list=new ArrayList<>();        Person person=null;        List<Element> children=rootElement.getChildren();        for(Element element:children){            person=new Person();            String personid=element.getAttributeValue("personid");            person.setPersonid(personid);            List<Element> children1=element.getChildren();            for(Element e:children1){                String tag=e.getName();                if("name".equals(tag)){                    person.setName(e.getText());                }else if("address".equals(tag)){                    person.setAddress(e.getText());                }else if("tel".equals(tag)){                    person.setTel(e.getText());                }else if("fax".equals(tag)){                    person.setFax(e.getText());                }else if("email".equals(tag)){                    person.setEmail(e.getText());                }            }            list.add(person);        }        System.out.println(Arrays.toString(list.toArray()));    }

6、DOM4J解析XML

dom4j是一个非常优秀的Java XML API,具有性能优异、功能强大和极端易用的特点,同时它也是一个开放源代码的软件,可以在SourceForge上找到它。Sun的JAXM也在使用dom4j,Hibernate用它来读写配置文件。

下载地址:https://dom4j.github.io/

    /**     * DOM4J 解析XML     * 基于树型结构,第三方组件     * 解析速度快,效率更高,使用Java中的迭代器实现数据读取,在web框架中使用较多(Hibernate)     */    @Test    public void dom4jParseXML() throws DocumentException {        //1.创建DOM4J的解析器对象        SAXReader  saxReader=new SAXReader();        InputStream is=Thread.currentThread().getContextClassLoader().getResourceAsStream("com/vince/xml/person.xml");        org.dom4j.Document document=saxReader.read(is);        org.dom4j.Element rootElement=document.getRootElement();        Iterator<org.dom4j.Element> iterator=rootElement.elementIterator();        ArrayList<Person> persons=new ArrayList<>();        Person p=null;        while (iterator.hasNext()){            p=new Person();            org.dom4j.Element e=iterator.next();            p.setPersonid(e.attributeValue("personid"));            Iterator<org.dom4j.Element> iterator1=e.elementIterator();            while (iterator1.hasNext()){                org.dom4j.Element next=iterator1.next();                String tag=next.getName();                if("name".equals(tag)){                    p.setName(next.getText());                }else if("address".equals(tag)){                    p.setAddress(next.getText());                }else if("tel".equals(tag)){                    p.setTel(next.getText());                }else if("fax".equals(tag)){                    p.setFax(next.getText());                }else if("email".equals(tag)){                    p.setEmail(next.getText());                }            }            persons.add(p);        }        System.out.println(Arrays.toString(persons.toArray()));    }

7、各种XML解析方法比较

这里写图片描述

在处理DOM的时候,我们需要读入整个的XML文档,然后在内存中创建DOM树,生成DOM树上的每个Node对象。当文档比较小的时候,这不会造成什么问题,但是一旦文档大起来,处理DOM就会变得相当费时费力。特别是其对于内存的需求,也将是成倍的增长,JDOM和DOM 在文档超过10M时易发生内存溢出。
SAX较轻量,是事件驱动,它并不需要读入整个文档,而文档的读入过程也就是SAX的解析过程。
DOM4J性能优异、功能强大和极端易用,许多开源项目中大量使用DOM4J。

8、通过对象生成XML文件

    /**     * 把对象转化为xml     */    @Test    public void xmlEnCoder() throws FileNotFoundException {        BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("test.xml"));        XMLEncoder xmlEncoder=new XMLEncoder(bos);        Person p=new Person();        p.setName("zxm");        p.setPersonid("123");        p.setEmail("zxm@qq.com");        p.setFax("1306123456");        p.setTel("1306123456");        p.setAddress("北京");        xmlEncoder.writeObject(p);        xmlEncoder.close();    }    /**     * 从XML文件读取对象     */    @Test    public void xmlDeCoder() throws FileNotFoundException{        BufferedInputStream in=new BufferedInputStream(new FileInputStream("test.xml"));        XMLDecoder decoder=new XMLDecoder(in);        Person p= (Person) decoder.readObject();        System.out.println(p);    }    /**     *使用第三方xStream组件实现XML的解析与生成,多用于传输数据时对字符串进行处理     * 需要导入xstream-1.4.10.jar和xpp3_min-1.1.4c.jar     */    @Test    public void XStream(){        Person p=new Person();        p.setName("zxm");        p.setPersonid("123");        p.setEmail("zxm@qq.com");        p.setFax("1306123456");        p.setTel("1306123456");        p.setAddress("北京");        XStream xStream = new XStream(new Xpp3Driver());        xStream.alias("person",Person.class);//为Person.class 设置别名为person        xStream.useAttributeFor(Person.class,"personid");//将personid子项作为Person.class的属性        String xml= xStream.toXML(p);        System.out.println(xml);        //解析XML        Person person = (Person)xStream.fromXML(xml);        System.out.println(person);    }

9、JSON

JSON(JavaScript Object Notation, JS 对象标记)是一种轻量级的数据交换格式。

JSON 构建于两种结构:
1、“名称/值”对的集合
如:{“firstName”:”vince”,”lastName”:”ma”,”age”:23}
2、值的有序列表(数组)
如:{“user”:[ {“firstName”:”vince”,”lastName”:”ma”,”age”:23} , {“firstName”:”Lily”,”lastName”:”Jack”,”age”:18} ]}

10、GSON组件的使用

GSON是Google开发的Java API,用于转换Java对象和Json对象。

下载地址:http://www.mvnrepository.com/artifact/com.google.code.gson/gson

解析json

例子:
解析message.json 文件

[  {    "id":912345678901,    "text":"How do I read a JSON stream in java?",    "geo":null,    "user":{      "name":"json_newb",      "followers_count":41    }  },  {    "id":912345678902,    "text":"@json_newb just use Json Reader!",    "geo":[50.45645,-654.46],    "user":{      "name":"jesse",      "followers_count":2    }  }]

根据要解析的json文件写实体类:
Message.java

public class Message {    private long id;    private String text;    private ArrayList<Double> geo;    private User user;    getter and setter...}

User.java

public class User {    private String name;    private int followers_count;    getter and setter...}
    @Test    public void parseJSONMessages(){        InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/vince/json/message.json");        InputStreamReader in=new InputStreamReader(is);        JsonReader jsonReader=new JsonReader(in);        ArrayList<Message> list=readMessageArray(jsonReader);        for (Message m:list) {            System.out.println(m);        }    }    //读取Message数组    private ArrayList<Message> readMessageArray(JsonReader jsonReader) {        ArrayList<Message> list=new ArrayList<>();        try {            jsonReader.beginArray();            while (jsonReader.hasNext()){                list.add(readMessage(jsonReader));            }            jsonReader.endArray();        } catch (IOException e) {            e.printStackTrace();        }        return list;    }    //解析一个Message对象    private Message readMessage(JsonReader jsonReader) {        Message m=new Message();        try {            jsonReader.beginObject();            while (jsonReader.hasNext()){                String name=jsonReader.nextName();                if("id".equals(name)){                    m.setId(jsonReader.nextLong());                }else if("text".equals(name)){                    m.setText(jsonReader.nextString());                }else if ("geo".equals(name)&&jsonReader.peek()!= JsonToken.NULL){                    m.setGeo(readGeo(jsonReader));                }else if ("user".equals(name)){                    m.setUser(readUser(jsonReader));                }else {                    jsonReader.skipValue();                }            }            jsonReader.endObject();        } catch (IOException e) {            e.printStackTrace();        }        return m;    }    //解析User对象    private User readUser(JsonReader jsonReader) {        User user=new User();        try {            jsonReader.beginObject();            while (jsonReader.hasNext()){                String name=jsonReader.nextName();                if("name".equals(name)){                    user.setName(jsonReader.nextString());                }else if ("followers_count".equals(name)){                    user.setFollowers_count(jsonReader.nextInt());                }else {                    jsonReader.skipValue();                }            }            jsonReader.endObject();        } catch (IOException e) {            e.printStackTrace();        }        return user;    }    //解析geo数组    private ArrayList<Double> readGeo(JsonReader jsonReader) {        ArrayList<Double> list=new ArrayList<>();        try {            jsonReader.beginArray();            while (jsonReader.hasNext()){                list.add(jsonReader.nextDouble());            }            jsonReader.endArray();        } catch (IOException e) {            e.printStackTrace();        }        return list;    }

生成json

    //将java对象转为json字符串    @Test    public void createJSON(){        List<Name> list=new ArrayList<>();        list.add(new Name("vince","ma","17834641@qq.com"));        list.add(new Name("jack","wang","jack@qq.com"));        JsonArray array=new JsonArray();        for (Name n:list) {            JsonObject obj=new JsonObject();            obj.addProperty("firstName",n.getFirstName());            obj.addProperty("lastName",n.getLastName());            obj.addProperty("email",n.getEmail());            array.add(obj);        }        System.out.println(array.toString());    }

JSON对象与JAVA对象的直接互转

    //把一个JSON对象转换为JAVA对象,或把一个JAVA对象转换成JSON对象    @Test    public void gson1(){        Gson gson=new Gson();        InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/vince/json/name.json");        InputStreamReader in=new InputStreamReader(is);        //把json转为name对象        Name name=gson.fromJson(in,Name.class);        System.out.println(name);        //将name对象转为json字符串        String json=gson.toJson(name);        System.out.println(json);    }    //把一组JSON对象转换成一个JAVA对象集合,或者把一个JAVA对象集合转换为一组JSON对象   @Test    public void gson2(){       Gson gson=new Gson();       InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/vince/json/names.json");       InputStreamReader in=new InputStreamReader(is);       TypeToken<List<Name>> typeToken = new TypeToken<List<Name>>(){};//相当于new了一个TypeToken的子类,为了指定泛型       List<Name> list=gson.fromJson(in,typeToken.getType());       System.out.println(list);       String json=gson.toJson(list,typeToken.getType());       System.out.println(json);   }

11、XML与JSON的比较

1、JSON和XML的数据可读性基本相同。
2、JSON和XML同样拥有丰富的解析手段
3、JSON相对于XML来讲,数据的体积小
4、JSON与JavaScript的交互更加方便
5、JSON对数据的描述性比XML较差
6、JSON的速度要远远快于XML

使用的场景:
数据传输:JSON速度更快
存储数据:MXL描述性更强
配置文件:用XML

原创粉丝点击