2021-09-22

XML & JSON文件详解以及解析

一、xml基础详解:

1、概述:

xml:即可扩展标记语言,xml是互联网数据传输的重要工具,它可以跨越互联网任何的平台,不受编程语言和操作系统的限制,可以说它是一个拥有互联网最高级别通行证的数据携带者。xml是当前处理结构化文档信息中相当给力的技术,xml有助于在服务器之间穿梭结构化数据,这使得开发人员更加得心应手的控制数据的存储和传输。

Xml用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。Xml是标准通用标记语言(SGML)的子集,非常适合Web传输。XML提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。

2、xml的特点及作用:

特点:

v xml与操作系统、编程语言的开发平台都无关;

v 实现不同系统之间的数据交互。

作用:

v 配置应用程序和网站;

v 数据交互;

v Ajax基石。

在配置文件里边所有的配置文件都是以XMl的格式来编写的。

跨平台进行数据交互,它可以跨操作系统,也可以跨编程语言的平台。

Ajax是现在目前比较流行的一个网络交互的技术。Ajax里面最后一个x实际上就是xml的缩写。Xml(Extensible Markup Language)是可扩展标记语言
在这里插入图片描述
一个xml文档必须要有第一行的声明和它的文档元素的描述信息就可以了。
3、xml声明

例子:
在这里插入图片描述
4、根元素
在这里插入图片描述
它是xml文档里面唯一的;它的开始是放在最前面,结束是放在最后面。
5、元素:
在这里插入图片描述
(1) 所有的xml元素都必须有结束标签;

(2) xml标签对大小写敏感;

在这里插入图片描述
(3) xml必须正确地嵌套;
在这里插入图片描述
(4)元素的命名规则:

名称中可以包含字母、数字或者其他的字符;

名称不能以数字或者标点符号开始;

名称中不能包含空格。

(5)空元素
在这里插入图片描述
6、属性

(1)语法

<元素名 属性名=“属性值”/>

例:

   <Name>Tom</Name>

(2)注意:

属性值用双引号包裹;一个元素可以有多个属性,它的基本格式为:

<元素名 属性名=“属性值” 属性名=“属性值”>;

属性值中不能够直接包含<.”,&。

7、实体:

在xml中,一些字符拥有特殊的意义。如果把字符“<”放在xml元素中,会发生错误,这是因为解析器会把它当作新元素的开始,这样会产生xml错误:
在这里插入图片描述
为了避免这个错误,请用实体引用来代替“<”字符:
在这里插入图片描述
xml中5个预定义实体
在这里插入图片描述
8、注释

注:注释内容中不要出现”–”;不要把注释放在标签中间;注释不能嵌套。

9、总结:

(1)xml描述的是文档的内容与语义,而不是文档应当如何显示;

(2)格式正规(well formed)的xml文档

遵循如下规则的xml文档称为格式正规的xml文档:

v 必须有xml声明语句;

v 必须有且仅有一个根元素;

v 标签大小写敏感;

v 属性值用双引号;

v 标签成对;

v 空标签关闭;

v 元素正确嵌套。

(3)有效的(valid)xml文档。首先xml文档是个格式正规的xml文档,然后又需要满足DTD的要求,这样的xml文档称为有效的xml文档;

10、解析器
在这里插入图片描述
11、命名空间

11.1、xml命名空间(xml Namespaces)

(1)xml命名空间提供避免元素命名冲突的方法。

(2)在xml中,元素名称是由开发者定义的,当两个不同的文档使用相同的元素名时,就会发生命名冲突。

11.2、xml命名空间示例
在这里插入图片描述
1)使用前缀示例
在这里插入图片描述

与仅仅使用前缀不同,我们为标签添加了一个xmlns属性,这样就为前缀赋予了一个与某个命名空间相关联的限定名称。

12、解析方式 _利用Java代码解析XML文档
l DOM:Document Object Model,文档对象模型。这种方式是W3C推荐的处理XML的一种标准方式。

缺点:必须读取整个XML文档,才能构建DOM模型,如果XML文档过大,造成资源的浪费。

优点:适合对XML中的数据进行操作(CRUD)。

l SAX:Simple API for XML。这种方式不是官方标准,属于开源社区XML-DEV,几乎所有的XML解析器都支持它。

12.2、解析工具
JAXP:

DOM或SAX方式进行解析XML。API在JDK之中。

Dom4J:(推荐)

是开源组织推出的解析开发包。(牛,大家都在用,包括SUN公司的一些技术的实现都在用)

13.3JAXP进行DOM方式解析XML基本练习
JAXP简介:
开发包:(JDK中)

DOM:W3C。org.w3c.dom.* DOM规范。(接口/抽象类)

SAX:开源组织。org.xml.sax.* SAX规范。(接口/抽象类)

JAXP:javax.xml.*

利用JAXP进行DOM方式解析
//JAXP进行DOM方式解析的基本操作

public class JaxpDemo1 {
 
	public static void main(String[] args) throws Exception {
		//得到解析器
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		//通过解析器就可以得到代表整个内存中XML的Document对象
		Document document = builder.parse("src/book.xml");
		test8(document);
	}
//	1、得到某个具体的节点内容:  刘丰
	private static void test1(Document document){
		NodeList nl = document.getElementsByTagName("作者");
		Node authorNode = nl.item(0);
		System.out.println(authorNode.getTextContent());
	}
//	2、遍历所有元素节点:打印元素的名称
	private static void test2(Node node){
		//确定node的类型
		//方式一
//		if(node.getNodeType()==Node.ELEMENT_NODE){
//			//是元素
//		}
		//方式二
		if(node instanceof Element){
			//是元素
			Element e = (Element)node;
			System.out.println(e.getNodeName());//打印元素名称
		}
		//判断有没有子节点
		NodeList nl = node.getChildNodes();
		for(int i=0;i<nl.getLength();i++){
			Node n = nl.item(i);
			test2(n);
		}
	}
//	3、修改某个元素节点的主体内容:<售价>39.00元</售价>--->10元
	private static void test3(Document document) throws Exception{
		//得到售价
		Node priceNode = document.getElementsByTagName("售价").item(0);
		priceNode.setTextContent("10元");
		//更新XML文件
		TransformerFactory tf = TransformerFactory.newInstance();
		Transformer t = tf.newTransformer();
		//构建输入源:
		Source source = new DOMSource(document);
		//构建目标:
		Result result = new StreamResult("src/book.xml");
		
		t.transform(source, result);
	}
	
//	4、向指定元素节点中增加子元素节点:第一本书添加子元素 <出版社>黑马程序员</出版社>
	private static void test4(Document document) throws Exception{
		//创建:<出版社>黑马程序员</出版社>
		Element e = document.createElement("出版社");
		e.setTextContent("黑马程序员");
		//得到书,把新节点挂上去
		Node bookNode = document.getElementsByTagName("书").item(0);
		bookNode.appendChild(e);
		//更新XML文件
		TransformerFactory tf = TransformerFactory.newInstance();
		Transformer t = tf.newTransformer();
		//构建输入源:
		Source source = new DOMSource(document);
		//构建目标:
		Result result = new StreamResult("src/book.xml");
		
		t.transform(source, result);
	}
//	5、向指定元素节点上增加同级元素节点:第一本书<售价>前面添加<批发价>30</批发价>
	private static void test5(Document document) throws Exception{
		//创建新节点
		Element e = document.createElement("批发价");
		e.setTextContent("30元");
		//找到<售价>
		Node priceNode = document.getElementsByTagName("售价").item(0);
		//父标签:调用insertBefore(新节点,参考节点);
		
		Node bookNode = priceNode.getParentNode();
		bookNode.insertBefore(e, priceNode);
		//更新XML文件
		TransformerFactory tf = TransformerFactory.newInstance();
		Transformer t = tf.newTransformer();
		//构建输入源:
		Source source = new DOMSource(document);
		//构建目标:
		Result result = new StreamResult("src/book.xml");
		
		t.transform(source, result);
	}
//	6、删除指定元素节点:删除批发价
	private static void test6(Document document) throws Exception{
		Node priceNode = document.getElementsByTagName("批发价").item(0);
		priceNode.getParentNode().removeChild(priceNode);
		//更新XML文件
		TransformerFactory tf = TransformerFactory.newInstance();
		Transformer t = tf.newTransformer();
		//构建输入源:
		Source source = new DOMSource(document);
		//构建目标:
		Result result = new StreamResult("src/book.xml");
		
		t.transform(source, result);
	}
//	7、操作XML文件属性:书籍添加一个属性:ISBN=“ABC”
	private static void test7(Document document) throws Exception{
		Node bookNode = document.getElementsByTagName("书").item(0);
		if(bookNode instanceof Element){
			Element e = (Element)bookNode;
			e.setAttribute("ISBN", "ABC");
		}
		//更新XML文件
		TransformerFactory tf = TransformerFactory.newInstance();
		Transformer t = tf.newTransformer();
		//构建输入源:
		Source source = new DOMSource(document);
		//构建目标:
		Result result = new StreamResult("src/book.xml");
		
		t.transform(source, result);
	}
//	8、操作XML文件属性:获取ISBN=“ABC”
	private static void test8(Document document) throws Exception{
		Node bookNode = document.getElementsByTagName("书").item(0);
		if(bookNode instanceof Element){
			Element e = (Element)bookNode;
			System.out.println(e.getAttribute("ISBN"));
		}
	}
}

sax解析原理
在使用 DOM 解析 XML 文档时,需要读取整个 XML 文档,在内存中构架代表整个 DOM 树的Doucment对象,从而再对XML文档进行操作。此种情况下,如果 XML 文档特别大,就会消耗计算机的大量内存,并且容易导致内存溢出。

SAX解析允许在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才会文档进行操作。

SAX采用事件处理的方式解析XML文件,利用 SAX 解析 XML 文档,涉及两个部分:解析器和事件处理器: 解析器可以使用JAXP的API创建,创建出SAX解析器后,就可以指定解析器去解析某个XML文档。 解析器采用SAX方式在解析某个XML文档时,它只要解析到XML文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的xml文件内容作为方法的参数传递给事件处理器。 事件处理器由程序员编写,程序员通过事件处理器中方法的参数,就可以很轻松地得到sax解析器解析到的数据,从而可以决定如何对数据进行处理
基本解析操作


```java
 //1解析器
    SAXParser parse = SAXParserFactory.newInstance().newSAXParser();
    //2获取xml读取器
    XMLReader reader = parse.getXMLReader();
    //3注册内容处理器
    reader.setContentHandler(new ContentHandler1());
    //4读取xml文档
    reader.parse("src/book.xml");

dom4j解析原理
Dom4j是一个简单、灵活的开放源代码的库。Dom4j是由早期开发JDOM的人分离出来而后独立开发的。与JDOM不同的是,dom4j使用接口和抽象基类,虽然Dom4j的API相对要复杂一些,但它提供了比JDOM更好的灵活性。 Dom4j是一个非常优秀的Java XML API,具有性能优异、功能强大和极易使用的特点。现在很多软件采用的Dom4j,例如Hibernate,包括sun公司自己的JAXM也用了Dom4j。 使用Dom4j开发,需下载dom4j相应的jar文件。

1、基本练习 a、拷贝jar包: 把dom4j-1.6.1.jar加入到你的classpath中 b、基本操作

// 1、得到某个具体的节点内容:金瓶梅

@Test
public void test1() throws Exception{
    SAXReader reader = new SAXReader();
    Document document = reader.read("src/book.xml");
    //首先要得到根元素
    Element root = document.getRootElement();
    List<Element> bookElements = root.elements();
//      Element bookName = (Element) bookElements.get(0).elements().get(0);
//      System.out.println(bookName.getText());
    System.out.println(bookElements.get(0).elementText("书名"));
}
// 2、遍历所有元素节点:名称

@Test
public void test2()throws Exception{
    SAXReader reader = new SAXReader();
    Document document = reader.read("src/book.xml");
    //首先要得到根元素
    Element root = document.getRootElement();
    treeWalk(root);
}
public void treeWalk(Element rootElement){//递归
    System.out.println(rootElement.getName());
    int nodeCount = rootElement.nodeCount();//子节点的数量
    for(int i=0;i<nodeCount;i++){
        Node node = rootElement.node(i);//得到一个子节点
        if(node instanceof Element){
            treeWalk((Element)node);
        }
    }
}
// 3、修改某个元素节点的主体内容:<售价>10元---20

@Test
public void test3()throws Exception{
    SAXReader reader = new SAXReader();
    Document document = reader.read("src/book.xml");
    //首先要得到根元素
    Element root = document.getRootElement();
    //得售价
    Element priceElement = root.element("书").element("售价");
    priceElement.setText("21元");
    //写回XML文档
//      OutputFormat format = OutputFormat.createCompactFormat();//去除空格回车换行,适合运行期间
    OutputFormat format = OutputFormat.createPrettyPrint();//漂亮的格式 默认编码是UTF-8
    XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"), format);
    writer.write(document);
    writer.close();
}
// 4、向指定元素节点中增加子元素节点:<出版社>黑马程序员

@Test
public void test4()throws Exception{
    SAXReader reader = new SAXReader();
    Document document = reader.read("src/book.xml");
    //首先要得到根元素
    Element root = document.getRootElement();
    //得售价
    Element bookElement = root.element("书");
    //创建新元素
    Element publisherElement = DocumentHelper.createElement("出版社");
    publisherElement.setText("黑马程序员");
 
    bookElement.add(publisherElement);
    //写回XML文档
//      OutputFormat format = OutputFormat.createCompactFormat();//去除空格回车换行,适合运行期间
    OutputFormat format = OutputFormat.createPrettyPrint();//漂亮的格式 默认编码是UTF-8
    XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"), format);
    writer.write(document);
    writer.close();
}
// 5、向指定元素节点上增加同级元素节点:<售价>21元 添加<批发价>

@Test
public void test5()throws Exception{
    SAXReader reader = new SAXReader();
    Document document = reader.read("src/book.xml");
    //首先要得到根元素
    Element root = document.getRootElement();
    //得售价
    Element bookElement = root.element("书");
    //创建新元素
    Element priceElement = DocumentHelper.createElement("批发价");
    priceElement.setText("30元");
 
    List<Element> bookChildren = bookElement.elements();//得到书的子元素
    bookChildren.add(2, priceElement);
 
    //写回XML文档
//      OutputFormat format = OutputFormat.createCompactFormat();//去除空格回车换行,适合运行期间
    OutputFormat format = OutputFormat.createPrettyPrint();//漂亮的格式 默认编码是UTF-8
    XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"), format);
    writer.write(document);
    writer.close();
}

// 6、删除指定元素节点:批发价

@Test
public void test6()throws Exception{
    SAXReader reader = new SAXReader();
    Document document = reader.read("src/book.xml");
    //首先要得到根元素
    Element root = document.getRootElement();
    Element priceElement = root.element("书").element("批发价");
 
    priceElement.getParent().remove(priceElement);
 
    //写回XML文档
//      OutputFormat format = OutputFormat.createCompactFormat();//去除空格回车换行,适合运行期间
    OutputFormat format = OutputFormat.createPrettyPrint();//漂亮的格式 默认编码是UTF-8
    XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"), format);
    writer.write(document);
    writer.close();
}
// 7、操作XML文件属性

@Test
public void test7()throws Exception{
    SAXReader reader = new SAXReader();
    Document document = reader.read("src/book.xml");
    //首先要得到根元素
    Element root = document.getRootElement();
    Element book = root.element("书");
    System.out.println(book.attributeValue("ISBN"));
}
@Test

public void test8()throws Exception{
    SAXReader reader = new SAXReader();
    Document document = reader.read("src/book.xml");
    //首先要得到根元素
    Element root = document.getRootElement();
    Element book = root.element("书");
    book.addAttribute("A", "B");
    //写回XML文档
//      OutputFormat format = OutputFormat.createCompactFormat();//去除空格回车换行,适合运行期间
    OutputFormat format = OutputFormat.createPrettyPrint();//漂亮的格式 默认编码是UTF-8
    XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"), format);
    writer.write(document);
    writer.close();
}

Xpath
XPath是一个努力为XSL转换XSLT和XPointer [ ] [ ]之间共享一个共同的XPointer功能语法和语义的结果。它的主要目的是解决一个XML XML文档部分[ ]。为了支持这一功能,还提供用于处理字符串的基本设施、数字和布尔值。XPath使用一个紧凑的、非XML语法方便使用在uri和XML属性值的XPath。XPath操作基于XML文档的逻辑结构,而不是其表面的语法。Xpath的名字来自其使用的符号在URL路径通过一个XML文档的层次结构导航。 除了用于定位,XPath还设计有一个真子集,可用于匹配(测试一个节点是否符合一个模式);使用XPath进行XSLT。

XPath模型的XML文档的节点树。有不同类型的节点,包括元素节点、属性节点和文本节点。XPath定义了一个方法来计算每个节点类型字符串值。某些类型的节点也有名字。XPath完全支持XML命名空间的XML名称] [。因此,一个节点的名称被建模为一个地方的部分和一个可能的空命名空间URI;这就是所谓的扩展名。在[ 5数据模型]中详细描述了数据模型。

@Test//Xpath

public void test11() throws Exception{
    SAXReader reader = new SAXReader();
    Document document = reader.read("src/book.xml");
    Node n = document.selectSingleNode("//书[1]/书名");
    System.out.println(n.getText());
}

@Test//Xpath:第一本书的ISBN的值

public void test12() throws Exception{
    SAXReader reader = new SAXReader();
    Document document = reader.read("src/book.xml");
    Node n = document.selectSingleNode("//书[1]");
    System.out.println(n.valueOf("@ISBN"));
}

xml约束之schema
XML Schema 也是一种用于定义和描述 XML 文档结构与内容的模式语言,其出现是为了克服 DTD 的局限性

XML Schema 文件自身就是一个XML文件,但它的扩展名通常为.xsd。支持名称空间。 一个XML Schema文档通常称之为模式文档(约束文档),遵循这个文档书写的xml文件称之为实例文档。

和XML文件一样,一个XML Schema文档也必须有一个根结点,但这个根结点的名称为schema。

编写了一个XML Schema约束文档后,通常需要把这个文件中声明的元素绑定到一个URI地址上,在XML Schema技术中有一个专业术语来描述这个过程,即把XML Schema文档声明的元素绑定到一个名称空间上,以后XML文件就可以通过这个URI(即名称空间)来告诉解析引擎,xml文档中编写的元素来自哪里,被谁约束。

学习目标:不需要我们编写xsd 重点:根据xsd编写出xml文档。 难点:在xml中引入xsd约束

基本操作步骤:
a、根据xsd文件,找到根元素

<?xml version="1.0" encoding="UTF-8"?>
<书架>
 
</书架>

b、根元素来在哪个名称空间 使用xmlns关键字来声明名称空间。

<?xml version="1.0" encoding="UTF-8"?>
<tf:书架 xmlns:tf="http://www.zhilinghui.com">
 
</tf:书架>
c、名称空间和哪个xsd文件对应

<?xml version="1.0" encoding="UTF-8"?>
<tf:书架 xmlns:tf="http://www.zhilinghui.com"
    schemaLocation="http://www.zhilinghui.com book.xsd">
 
</tf:书架>
d、schemaLocation来自一个标准的名称空间:固定写法

<?xml version="1.0" encoding="UTF-8"?>
<tf:书架 xmlns:tf="http://www.zhilinghui.com"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.zhilinghui.com book.xsd">
 
</tf:书架>

————————————————
版权声明:本文为CSDN博主「朱培」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/sdksdk0/article/details/50749326

二. JSON三种数据解析方法

JSON数据现在是我们开发中用的最多的,百分之九十的数据都是通过JSON方式进行传输,那么想要学好JSON解析就要了解什么是JSON数据,怎么快速解析它从而提升开发效率。

1 什么是JSON数据?
先看下面,这里有一段JSON数据,我们根据这段数进行讲解:


```java
{   "paramz": {
    "feeds": [
      {
        "id": 299076,
        "oid": 288340,
        "category": "article",
        "data": {
          "subject": "荔枝新闻3.0:不止是阅读",
          "summary": "江苏广电旗下资讯类手机应用“荔枝新闻”于近期推出全新升级换代的3.0版。",
          "cover": "/Attachs/Article/288340/3e8e2c397c70469f8845fad73aa38165_padmini.JPG",
          "pic": "",
          "format": "txt",
          "changed": "2015-09-22 16:01:41"
        }
      }
    ],
    "PageIndex": 1,
    "PageSize": 20,
    "TotalCount": 53521,
    "TotalPage": 2677   
    } 
  }


其实JSON数据就是一段字符串而已,只不过有不同意义的分隔符将其分割开来而已,我们看上面的符号,里面有[] ,{}等符号,其中

1 []中括号代表的是一个数组;
2 {}大括号代表的是一个对象
3 双引号“”表示的是属性值
4 冒号:代表的是前后之间的关系,冒号前面是属性的名称,后面是属性的值,这个值可以是基本数据类型,也可以是引用数据类型。
2 了解了JSON数据的格式,怎么对这段数据进行解析呢?
JSONObject系统自带的解析方式解析,我们先来JSONObject(系统自带的类)类中的方法:



上面用红框框出来的是我们手动解析最常用的方法了,好了,现在我们想要解析上面的一段数据,该怎么做呢?这里我写了一个解析类如下:

```java
public class JsonUtils {

    /**
     * 根据json数据解析返回一个List<HashMap<String, Object>>集合
     * @param json  json数据
     * @return
     */
    public static List<HashMap<String, Object>> getJsonList(String json) {
        List<HashMap<String, Object>> dataList;
        dataList = new ArrayList<>();
        try {
            JSONObject rootObject = new JSONObject(json);
            JSONObject paramzObject = rootObject.getJSONObject("paramz");
            JSONArray feedsArray = paramzObject.getJSONArray("feeds");
            for (int i = 0; i < feedsArray.length(); i++) {
                JSONObject sonObject = feedsArray.getJSONObject(i);
                JSONObject dataObject = sonObject.getJSONObject("data");
                String subjectStr = dataObject.getString("subject");
                String summaryStr = dataObject.getString("summary");
                String coverStr = dataObject.getString("cover");
                HashMap<String, Object> map = new HashMap<>();
                map.put("subject", subjectStr);
                map.put("summary", summaryStr);
                map.put("cover", coverStr);
                dataList.add(map);
            }
            return dataList;
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }
}

相信很简单一看就懂了吧,此方法写起来主要是比较费时间罢了,无非就是几个方法不停的调用而已,所以显得特别的费时费力,下面我又写了一个解析的方法,方法中会有一些冗余的代码,是为了更加深刻理解JSON解析而写的,实际中可以删掉,也用了一行GSON解析,GSON解析下面会见讲到:

其中DataModel对象我是将data对象使用GsonFormat插件工具生成的,使用方式可以自行搜索

public class DataModel {

    /**
     * subject : "荔枝新闻3.0:不止是阅读"
     * summary : "江苏广电旗下资讯类手机应用“荔枝新闻”于近期推出全新升级换代的3.0版。"
     * cover : "/Attachs/Article/288340/3e8e2c397c70469f8845fad73aa38165_padmini.JPG"
     * pic :
     * format : video
     * changed : 2015-11-07 14:35:22
     */

    public String subject;
    public String summary;
    public String cover;
    public String pic;
    public String format;
    public String changed;

    @Override
    public String toString() {
        return "DataModel{" +
                "subject='" + subject + '\'' +
                ", summary='" + summary + '\'' +
                ", cover='" + cover + '\'' +
                ", pic='" + pic + '\'' +
                ", format='" + format + '\'' +
                ", changed='" + changed + '\'' +
                '}';
    }
}
 /**
     * 根据json对象获取List<DataModel>集合
     * @param json 数据
     * @return
     */
    public static List<DataModel> getGsonList(String json) {
        List<DataModel> dataList;
        try {
            JSONObject rootObject = new JSONObject(json);
            JSONObject paramzObject = rootObject.getJSONObject("paramz");

            /**
             * JSONArray的构造方法获取JSONArray对象
             */
            JSONArray jsonArray = new JSONArray(paramzObject.getString("feeds"));
            Log.i(TAG, "jsonarray.length():"+jsonArray.length());

            /**
             * 获取JSONObject对象的属性关键字
             */
            Iterator<String> iterators = paramzObject.keys();
            while (iterators.hasNext()) {
                Log.i(TAG, "iterators: " + iterators.next());
            }
            JSONArray feeds = paramzObject.getJSONArray("feeds");
            dataList = new ArrayList<>();
            for (int i = 0; i < feeds.length(); i++) {
                JSONObject jsonObject = feeds.getJSONObject(i);
                DataModel model = new Gson().fromJson(jsonObject.getString("data"), new TypeToken<DataModel>() {
                }.getType());
                Log.i(TAG, "DataModel: " + model.toString());
                dataList.add(model);
            }
            return dataList;
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return null;
    }

简单总结一下上面的解析吧:

1 对于JSONObject对象来说,想要得到一个JSONObject对象通常可以通过

(a):构造方式:JSONObject(String json)-> JSONObject rootObject = new JSONObject(json);
(b):JSONObject getJSONObject(String name){}-> JSONObject paramzObject = rootObject.getJSONObject(“paramz”);
2 对于JSONArray对象来说,想要得到一个JSONArray对象通常可以通过

(a):构造方式:JSONArray(String json)->JSONArray jsonArray = new JSONArray(paramzObject.getString(“feeds”));
(b):JSONObject getJSONObject(String name){}-> JSONArray feeds = paramzObject.getJSONArray(“feeds”);

3 Gson解析
我们如果懂得了上面的手动解析方式的话,那么对于Gson解析而言,就太简单了,下面我们就开始解析下面一段JSON数据:

{
    "homeadlist": [
        {
            "id": 1,
            "imgurl": "/img/homead/a73b3f1d-0f14-429d-9d0f-70643fb0f0eb.jpg",
            "jumpflag": 0,
            "jumpurl": "",
            "posflag": 1,
            "remark": "1111",
            "cityid": 1
        },
        {
            "id": 12,
            "imgurl": "/img/homead/eb442fbf-49db-4ba6-a102-d781505f426d.jpg",
            "jumpflag": 0,
            "jumpurl": "",
            "posflag": 2,
            "remark": "",
            "cityid": 1
        },
        {
            "id": 14,
            "imgurl": "/img/homead/68109460-635d-4c5c-8be8-64d7c7889d18.jpg",
            "jumpflag": 0,
            "jumpurl": "http://shiranlife.kuaizhan.com/",
            "posflag": 4,
            "remark": "",
            "cityid": 1
        }
    ]
}

首先我们使用GsonFormat工具生成一个类HomeadListModel:

public class HomeadListModel {

    /**
     * code : 1
     * data : {"homeadlist":[{"id":1,"imgurl":"/img/homead/a73b3f1d-0f14-429d-9d0f-70643fb0f0eb.jpg","jumpflag":0,"jumpurl":"","posflag":1,"remark":"1111","cityid":1},{"id":12,"imgurl":"/img/homead/eb442fbf-49db-4ba6-a102-d781505f426d.jpg","jumpflag":0,"jumpurl":"","posflag":2,"remark":"","cityid":1},{"id":14,"imgurl":"/img/homead/68109460-635d-4c5c-8be8-64d7c7889d18.jpg","jumpflag":0,"jumpurl":"http://shiranlife.kuaizhan.com/","posflag":4,"remark":"","cityid":1}]}
     */

    public int code;
    public DataBean data;

    public static class DataBean {
        public List<HomeadlistBean> homeadlist;

        public static class HomeadlistBean {
            public int id;
            public String imgurl;
            public int jumpflag;
            public String jumpurl;
            public int posflag;
            public String remark;
            public int cityid;
        }
    }
}

我们使用OKHttpClient,代码如下

OkHttpClient.Builder builder = new OkHttpClient.Builder();

        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();

        builder.build().newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Gson gson = new Gson();
                /**
                 * java.lang.IllegalStateException: closed
                 * 因为OkHttp请求回调中response.body().string()只能有效调用一次
                 *
                 */

                String string = response.body().string();
                Log.i("aaa", "response: " + string);
                /**
                 * 重新构建一个response 因为response.body().string()调用一次之后流就断掉了,只能有效调用一次
                 */
                MediaType mediaType = response.body().contentType();
                Response response1 = response.newBuilder().body(ResponseBody.create(mediaType, string)).build();
                String string1 = response1.body().string();
                Log.i("aaa", "response1: " + string1);
                /**
                 * 将json数据转换为对象
                 */
                HomeadListModel model = gson.fromJson(string1, HomeadListModel.class);
                //HomeadListModel model2 = gson.fromJson(string1, new TypeToken<HomeadListModel>() {
                }.getType());
                /**
                 * 将对象转换为json数据
                 */
                String jsonString = gson.toJson(model);
                Log.i("aaa", "onResponse2: " + jsonString);

                for (HomeadListModel.DataBean.HomeadlistBean data : model.data.homeadlist) {
                    mData.add(imageUrl + data.imgurl);
                }
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mAdapter.notifyDataSetChanged();
                    }
                });
            }
        });

我们想要将一个json数据转换为对象的话需要使用fromJson(String json, Class classOfT) /fromJson(String json, Type typeOfT),当我们需要将对象转换为String的时候根据String toJson(Object src)方法即可。这里需要注意一点,如果response.body().string()调用大于一次的话,就会报错java.lang.IllegalStateException: closed,因为response.body().string()调用一次之后流就断掉了,需要重新构建一个response;

4 FastJson解析
这个解析和Gson解析差不多,也是一行就搞定了,也是对上面的Gson数据进行解析,想要将json数据解析成对象需要使用 parseObject()方法,参数可以传Class,也可以传Type;当需要通过对象得到String字符串时候使用String json1 = JSONObject.toJSONString(model)即可,下面贴上代码:

OkHttpClient.Builder builder = new OkHttpClient.Builder();
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();
        builder.build().newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {

                String json = response.body().string();
                /**
                 * 根据json数据获取对象
                 */
                HomeadListModel model = JSONObject.parseObject(json, new TypeToken<HomeadListModel>() {
                }.getType());
//                HomeadListModel model2 = JSONObject.parseObject(json, HomeadListModel.class);

                /**
                 * 根据对象获取json数据
                 */
                String json1 = JSONObject.toJSONString(model);
                Log.i("aaa", "fastJson: " + json1);

                for (HomeadListModel.DataBean.HomeadlistBean data : model.data.homeadlist) {
                    mData.add(imageUrl + data.imgurl);
                }
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mAdapter.notifyDataSetChanged();
                    }
                });
            }
        });

结尾:上面写了三种解析JSON数据的方法,第一种是最麻烦的,但是不一定是最差的,后面两种Gson和FastJson都是最常用的方法,本博客里面用到的API也是最常用的API,基本开发都够用了,其余未涉及到的请自行查看源码学习吧。

原文链接:https://blog.csdn.net/oman001/article/details/79063278

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值