首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android开发笔记(六十二)HTTP数据格式的解析

Android开发笔记(六十二)HTTP数据格式的解析

作者头像
aqi00
发布2019-01-18 11:08:41
1.3K0
发布2019-01-18 11:08:41
举报
文章被收录于专栏:老欧说安卓老欧说安卓

json解析

android有两种主流的json解析方案,一种是sdk自带的由Google提供的json(包名前缀为org.json),另一种是Alibaba提供的第三方jar包fastjson(包名前缀为com.alibaba.fastjson)。

json

json的常用方法有: JSONObject构造函数 : 从指定字符串构造出一个JSONObject对象 JSONObject.getJSONObject : 获取指定名称的JSONObject对象 JSONObject.getString : 获取指定名称的字符串值 JSONObject.put : 添加一个json元素 JSONObject.toString : 把当前JSONObject输出为一个json字符串 JSONObject.getJSONArray : 获取指定名称的json对象数组 JSONArray.length : 获取json对象数组的大小 JSONArray.getJSONObject : 获取json对象数组在指定位置处的JSONObject对象 JSONArray.put : 往json对象数组中添加一个JSONObject对象

fastjson

fastjson的常用方法有: JSONObject.parseObject : 静态函数,由指定字符串解析出一个JSONObject对象 JSONObject.getJSONObject : 获取指定名称的JSONObject对象 JSONObject.getString : 获取指定名称的字符串值 JSONObject.put : 添加一个json元素 JSONObject.toString : 把当前JSONObject输出为一个json字符串 JSONObject.getJSONArray : 获取指定名称的json对象数组 JSONArray.size : 获取json对象数组的大小 JSONArray.getJSONObject : 获取json对象数组在指定位置处的JSONObject对象 JSONArray.add : 往json对象数组中添加一个JSONObject对象 json和fastjson的用法主要有如下区别: 1、从字符串创建一个JSONObject对象,json调用的是JSONObject的parseObject方法;而fastjson调用的是JSONObject的parseObject方法。 2、获取一个JSONArray对象的大小,json调用的是JSONArray的length方法;而fastjson调用的是JSONArray的size方法。 3、往JSONArray中添加一个JSONObject,json调用的是JSONArray的put方法;而fastjson调用的是JSONArray的add方法。

效果图与示例代码

在前面的《Android开发笔记(四十六)手机相关事件》中,介绍了如何根据定位事件获得当前位置的经度和纬度值,可惜定位事件没法知道当前的详细地址。现在我们利用google map的开放api,传入经纬度的数值,成功的话google会返回一个json字符串,通过解析这个json串就能得到具体的地址名称。下面是json解析的效果截图:

下面是json方式的解析和组包代码示例:

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class JsonGoogle {

    public static String parserAddress(String jsonString) {
    	String address = "";
        try {
            JSONObject obj = new JSONObject(jsonString);
            JSONArray resultArray = obj.getJSONArray("results");
            if (resultArray.length() > 0) {
                JSONObject resultObj = resultArray.getJSONObject(0);
                address = resultObj.getString("formatted_address");
            }
        }catch (JSONException e) {
            e.printStackTrace();
        }
        return address;
    }

    public static String formatTest() {
    	String str = "";
    	JSONObject obj = new JSONObject();
    	try {
			obj.put("name", "address");
			JSONArray array = new JSONArray();
			for (int i = 0; i < 3; i++) {
				JSONObject item = new JSONObject();
				item.put("item", "第" + (i + 1) + "个元素");
				array.put(item);
			}
			obj.put("list", array);
			obj.put("count", array.length());
	    	obj.put("desc", "这是测试串");
			str = obj.toString();
		} catch (JSONException e) {
			e.printStackTrace();
		}
    	return str;
    }

}

下面是fastjson方式的解析和组包代码示例:

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;

public class JsonAlibaba {

    public static String parserAddress(String jsonString) {
    	String address = "";
        try {
        	JSONObject obj = JSONObject.parseObject(jsonString);
            JSONArray resultArray = obj.getJSONArray("results");
            if (resultArray.size() > 0) {
                JSONObject resultObj = resultArray.getJSONObject(0);
                address = resultObj.getString("formatted_address");
            }
        }catch (JSONException e) {
            e.printStackTrace();
        }
        return address;
    }

    public static String formatTest() {
    	String str = "";
    	JSONObject obj = new JSONObject();
    	obj.put("name", "address");
    	JSONArray array = new JSONArray();
    	for (int i=0; i<3; i++) {
        	JSONObject item = new JSONObject();
        	item.put("item", "第"+(i+1)+"个元素");
        	array.add(item);
    	}
    	obj.put("list", array);
		obj.put("count", array.size());
    	obj.put("desc", "这是测试串");
    	str = obj.toString();
    	return str;
    }

}

xml解析

xml解析在android上有三种解决方案,一种是android自带的pull,另外两种是行业标准的sax和dom。

pull

pull在解析xml时是边读取边解析,这种处理方式类似sax,同时pull与sax相比,解析更加方便快速,更适合用于移动平台。pull的常见方法都来自于XmlPullParser类,具体如下: setInput : 设置解析的输入流。 getEventType : 获取当前节点的事件类型。START_DOCUMENT表示解析开始,START_TAG表示一个标记开始,END_TAG表示一个标记结束。 getName : 获取当前节点的名称。 nextText : 获取当前节点的文本。 next : 解析下一个节点。返回值是下一个节点的事件类型。 getAttributeName : 获取当前节点在指定位置的属性名称。 getAttributeValue : 获取当前节点在指定位置的属性值。

sax

sax也是边读取边解析xml,与pull相比,sax在处理上有些繁琐。首先要写个新类继承自DefaultHandler,然后依次实现下面的函数,最后调用SAXParser的parse函数完成解析操作: startDocument : 表示解析开始 startElement : 表示开始解析某个节点 characters : 表示开始解析某个节点的文本 endElement : 表示完成解析某个节点

dom

dom是先把整个输入流都读取进来,建立好一个完整的节点树,然后由用户去读取指定节点。由于是整个读取,因此在效率上不够高,不建议在移动平台上应用dom。如果想在建树完毕后再遍历所有节点,大致流程为:先调用DocumentBuilder的parse方法设置输入流,获得一个Document对象;然后调用Document对象的getDocumentElement方法,获得根节点的Element对象;接着调用Element对象的getFirstChild方法,获得根节点下面的第一个子节点Node对象,通过getNodeName和getNodeValue可以分别获得节点名称和节点值;调用Node对象的getNextSibling方法,可以获得下一个节点对象,接着处理下一个节点;如果下一个节点对象为空,则表示输入流解析完毕。

效果图与实例代码

下面是xml解析的效果截图:

下面是pull方式的解析代码示例:

import java.io.StringReader;
import java.io.StringWriter;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlSerializer;

import android.util.Log;
import android.util.Xml;

public class XmlPull {
	private final static String TAG = "XmlPull";

	public static String parser(String src) {
		String desc = "";
		boolean bRoot = true;
		boolean bList = false;
		StringReader strReader = new StringReader(src);
		XmlPullParser parser = Xml.newPullParser();
        try {
			parser.setInput(strReader);
			int eventType = parser.getEventType();
			while (eventType != XmlPullParser.END_DOCUMENT) {
				String name = "";
				switch (eventType) {
				case XmlPullParser.START_DOCUMENT:
					bRoot = true;
					bList = false;
					break;
				case XmlPullParser.START_TAG:
					name = parser.getName();
					if (bRoot == true) {
						desc = String.format("%sPull解析的根节点为:%s。其中\n", desc, name);
						bRoot = false;
						break;
					}
					if (name.equals("list") == true) {
						desc = String.format("%s\t数组%s的元素列表如下\n", desc, name);
						bList = true;
					} else if (bList == true) {
						if (name.equals("item") == true) {
							desc = String.format("%s\t\t元素%s的属性名称为:%s,属性值为:%s\n", 
									desc, name, parser.getAttributeName(0), parser.getAttributeValue(0));
						} else {
							desc = String.format("%s\t\t\t节点%s的值为:%s\n", 
									desc, name, parser.nextText());
						}
					} else {
						desc = String.format("%s\t节点%s的值为:%s\n", desc, name, parser.nextText());
					}
					break;
				case XmlPullParser.END_TAG:
					name = parser.getName();
					if (name.equals("list") == true) {
						bList = false;
					}
					break;
				}
				Log.d(TAG, "eventType="+eventType+", name="+name);
				eventType = parser.next();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return desc;
	}

	public static String format() {
		StringWriter strWriter = new StringWriter();
        XmlSerializer serializer = Xml.newSerializer();
        try {
			serializer.setOutput(strWriter);
	        serializer.startDocument("UTF-8", true);
	        serializer.startTag(null, "content");

	        serializer.startTag(null, "name");
	        serializer.text("address");
	        serializer.endTag(null, "name");

	        int count = 3;
	        serializer.startTag(null, "list");
	        for (int i=0; i<count; i++) {
	            serializer.startTag(null, "item");
	            serializer.attribute(null, "id", i+"");
	            
	            serializer.startTag(null, "value");
	            String value = "第" + (i + 1) + "个元素";
	            serializer.text(value);
	            serializer.endTag(null, "value");
	            
	            serializer.endTag(null, "item");
	        }
	        serializer.endTag(null, "list");

	        serializer.startTag(null, "count");
	        serializer.text(count+"");
	        serializer.endTag(null, "count");

	        serializer.startTag(null, "desc");
	        serializer.text("这是Pull构造的XML测试串");
	        serializer.endTag(null, "desc");

	        serializer.endTag(null, "content");
	        serializer.endDocument();
		} catch (Exception e) {
			e.printStackTrace();
		}
        return strWriter.toString();
	}

}

下面是sax方式的解析代码示例:

import java.io.ByteArrayInputStream;
import java.io.InputStream;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class XmlSax extends DefaultHandler {
	private String desc = "";
	private boolean bRoot = true;
	private boolean bList = false;
	private String mTag = "";
	
	public String toString() {
		return desc;
	}
	
	@Override
	public void startDocument() throws SAXException {
		bRoot = true;
		bList = false;
	}
	
	@Override
	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
		if (bRoot == true) {
			desc = String.format("%sSax解析的根节点为:%s。其中\n", desc, localName);
			bRoot = false;
		}
		if (localName.equals("list") == true) {
			desc = String.format("%s\t数组%s的元素列表如下\n", desc, localName);
			bList = true;
		} else if (bList == true) {
			if (localName.equals("item") == true) {
				desc = String.format("%s\t\t元素%s的属性名称为:%s,属性值为:%s\n", 
						desc, localName, attributes.getLocalName(0), attributes.getValue(0));
			}
		}
		mTag = localName;
	}
	
	@Override
	public void characters(char[] ch, int start, int length) throws SAXException {
		if (mTag!=null && mTag.length()>0) {
			String value = new String(ch , start , length);
			if (bList == true) {
				desc = String.format("%s\t\t\t节点%s的值为:%s\n", 
						desc, mTag, value);
			} else {
				desc = String.format("%s\t节点%s的值为:%s\n", desc, mTag, value);
			}
		}
	}
	
	@Override
	public void endElement(String uri, String localName, String qName) throws SAXException {
		if (localName.equals("list") == true) {
			bList = false;
		}
	}
	
	public static String parser(String src) {
		String desc = "";
		try {
			SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
			InputStream inStream = new ByteArrayInputStream(src.getBytes());
			XmlSax saxParser = new XmlSax();
			parser.parse(inStream, saxParser);
			inStream.close();
			desc = saxParser.toString();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return desc;
	}
	
}

下面是dom方式的解析代码示例:

import java.io.ByteArrayInputStream;
import java.io.InputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class XmlDom {

	public static String parser(String src) {
		String desc = "";
		InputStream inStream = new ByteArrayInputStream(src.getBytes());
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		try {
			DocumentBuilder builder = factory.newDocumentBuilder();
	        Document document = builder.parse(inStream);
	        Element root = document.getDocumentElement();
			desc = String.format("%sDom解析的根节点为:%s。其中\n", desc, root.getTagName());
	        Node node = root.getFirstChild();
	        do {
	        	String node_name = node.getNodeName();
		        if (node_name.equals("list") != true) {
					desc = String.format("%s\t节点%s的值为:%s\n", desc, node_name, node.getFirstChild().getNodeValue());
		        } else {
					desc = String.format("%s\t数组%s的元素列表如下\n", desc, node_name);
			        NodeList itemList = root.getElementsByTagName("item");
			        for (int i=0; i<itemList.getLength(); i++) {
			        	Node item = itemList.item(i);
			        	if (item.getNodeType() == Node.ELEMENT_NODE) {
				        	NamedNodeMap attr_map = item.getAttributes();
				        	Node attr = attr_map.item(0);
							desc = String.format("%s\t\t元素%s的属性名称为:%s,属性值为:%s\n", 
									desc, item.getNodeName(), attr.getNodeName(), attr.getNodeValue());
					        Node item_node = item.getFirstChild();
					        do {
								desc = String.format("%s\t\t\t节点%s的值为:%s\n", 
										desc, item_node.getNodeName(), item_node.getFirstChild().getNodeValue());
					        	item_node = item_node.getNextSibling();
					        } while (item_node != null);
			        	}
			        }
		        }
	        	node = node.getNextSibling();
	        } while (node != null);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return desc;
	}
	
}

html解析

android解析html网页可使用开源库jsoup,把jsoup-1.8.1.jar加入到工程的libs目录,即可在工程中调用jsoup的解析方法。 jsoup的解析分为三个层次,第一级是Document,表示整个html网页;第二级是Element,表示某个组件及其下面的元素;第三级是Node,表示某个具体的节点。下面介绍这三个层级的主要用法: Document:它由Jsoup类的parse函数解析而来,解析的来源可以是字符串String,也可以是文件File,也可以是输入流InputStream,还可以是网址Url。另外,Document继承自Element,因此拥有Element的所有方法; Element:可由Document先select再get获取某个名称的组件得到。下面是Element的常用方法: ——select : 获取指定名称的组件数组Elements,获取具体的Element可再调用Elements的get方法; ——text : 获取当前组件下的所有文本。不同节点的文本以空格连接。 ——attr : 获取指定属性名称的属性值。 Node:虽然Element继承自Node,但是一般Element就够用了,所以Node用得不多。 下面是jsoup解析html的示例代码:

import java.util.ArrayList;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

import com.example.exmparser.adapter.NoticeItem;

public class HtmlJsoup {

	public static ArrayList<NoticeItem> parser(String content) {
		ArrayList<NoticeItem> notice_list = new ArrayList<NoticeItem>();
		Document doc = Jsoup.parse(content);
		Element link_tr_e = null;
		for (int i = 0;; i++) {
			try {
				link_tr_e = doc.select("tr").get(i);
				String link_tr_s = link_tr_e.text();
				if (link_tr_s.length() < 20) {
					continue;
				}
			} catch (IndexOutOfBoundsException ex) {
				break;
			}
			Element link_td_e = null;
			NoticeItem notice = new NoticeItem();
			for (int j=0;; j++) {
				try {
					link_td_e = link_tr_e.select("td").get(j);
				} catch (IndexOutOfBoundsException ex) {
					break;
				}
				if (link_td_e.attr("class").equals("list") == true) {
					Element link_a_e = link_td_e.select("a").get(0);
					notice.title = link_a_e.attr("title");
					notice.url = link_a_e.attr("href");
				} else if (link_td_e.attr("class").equals("time") == true) {
					notice.date = link_td_e.text().replace("(", "").replace(")", "")
							.replace("(", "").replace(")", "");
				}
			}
			if (notice.url.equals("") != true) {
				notice_list.add(notice);
			}
		}
//		Log.d(TAG, "notice_list.size()=" + notice_list.size());
//		Log.d(TAG, "");
//		for (int i = 0; i < notice_list.size(); i++) {
//			Log.d(TAG, "公告标题=" + notice_list.get(i).title);
//			Log.d(TAG, "访问链接=" + notice_list.get(i).url);
//			Log.d(TAG, "发布日期=" + notice_list.get(i).date);
//			Log.d(TAG, "");
//		}
		return notice_list;
	}

}

点击下载本文用到的HTTP数据格式解析的工程代码 点此查看Android开发笔记的完整目录

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016年02月12日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • json解析
    • json
      • fastjson
        • 效果图与示例代码
        • xml解析
          • pull
            • sax
              • dom
                • 效果图与实例代码
                • html解析
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档