Android学习笔记 - DOM SAX PULL JSON

Dom 创建 XML

Dom,借助 javax.xml.parsers.DocumentBuilder,可以创建 org.w3c.dom.Document 对象。

使用来自 DocumentBuilderFactory 的 DocumentBuilder 对象在 Android 设备上创建与解析 XML 文档。您将使用 XML pull 解析器的扩展来解析 XML 文档。

Code

[java]  view plain copy print ?
  1. /** Dom方式,创建 XML  */  
  2. public String domCreateXML() {  
  3.     String xmlWriter = null;  
  4.       
  5.     Person []persons = new Person[3];       // 创建节点Person对象  
  6.     persons[0] = new Person(1"sunboy_2050""http://blog.csdn.net/sunboy_2050");  
  7.     persons[1] = new Person(2"baidu""http://www.baidu.com");  
  8.     persons[2] = new Person(3"google""http://www.google.com");  
  9.       
  10.     try {  
  11.         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();  
  12.         DocumentBuilder builder = factory.newDocumentBuilder();  
  13.         Document doc = builder.newDocument();  
  14.           
  15.         Element eleRoot = doc.createElement("root");  
  16.         eleRoot.setAttribute("author""homer");  
  17.         eleRoot.setAttribute("date""2012-04-26");  
  18.         doc.appendChild(eleRoot);  
  19.           
  20.         int personsLen = persons.length;  
  21.         for(int i=0; i<personsLen; i++) {  
  22.             Element elePerson = doc.createElement("person");  
  23.             eleRoot.appendChild(elePerson);  
  24.               
  25.             Element eleId = doc.createElement("id");  
  26.             Node nodeId = doc.createTextNode(persons[i].getId() + "");  
  27.             eleId.appendChild(nodeId);  
  28.             elePerson.appendChild(eleId);  
  29.   
  30.             Element eleName = doc.createElement("name");  
  31.             Node nodeName = doc.createTextNode(persons[i].getName());  
  32.             eleName.appendChild(nodeName);  
  33.             elePerson.appendChild(eleName);  
  34.   
  35.             Element eleBlog = doc.createElement("blog");  
  36.             Node nodeBlog = doc.createTextNode(persons[i].getBlog());  
  37.             eleBlog.appendChild(nodeBlog);  
  38.             elePerson.appendChild(eleBlog);  
  39.         }  
  40.           
  41.           
  42.         Properties properties = new Properties();  
  43.         properties.setProperty(OutputKeys.INDENT, "yes");  
  44.         properties.setProperty(OutputKeys.MEDIA_TYPE, "xml");  
  45.         properties.setProperty(OutputKeys.VERSION, "1.0");  
  46.         properties.setProperty(OutputKeys.ENCODING, "utf-8");  
  47.         properties.setProperty(OutputKeys.METHOD, "xml");  
  48.         properties.setProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");  
  49.           
  50.         TransformerFactory transformerFactory = TransformerFactory.newInstance();  
  51.         Transformer transformer = transformerFactory.newTransformer();  
  52.         transformer.setOutputProperties(properties);  
  53.           
  54.         DOMSource domSource = new DOMSource(doc.getDocumentElement());  
  55.         OutputStream output = new ByteArrayOutputStream();  
  56.         StreamResult result = new StreamResult(output);  
  57.         transformer.transform(domSource, result);  
  58.           
  59.         xmlWriter = output.toString();  
  60.           
  61.     } catch (ParserConfigurationException e) {      // factory.newDocumentBuilder  
  62.         e.printStackTrace();  
  63.     } catch (DOMException e) {                      // doc.createElement  
  64.         e.printStackTrace();  
  65.     } catch (TransformerFactoryConfigurationError e) {      // TransformerFactory.newInstance  
  66.         e.printStackTrace();  
  67.     } catch (TransformerConfigurationException e) {     // transformerFactory.newTransformer  
  68.         e.printStackTrace();  
  69.     } catch (TransformerException e) {              // transformer.transform  
  70.         e.printStackTrace();  
  71.     } catch (Exception e) {  
  72.         e.printStackTrace();  
  73.     }  
  74.       
  75.     savedXML(fileName, xmlWriter.toString());  
  76.       
  77.     return xmlWriter.toString();  
  78. }  

运行结果:




DOM解析XML文件时,会将XML文件的所有内容读取到内存中,然后允许您使用DOM API遍历XML树、检索所需的数据。使用DOM操作XML的代码看起来比较直观,并且,在某些方面比基于SAX的实现更加简单。但是,因为DOM需要将XML文件的所有内容读取到内存中,所以内存的消耗比较大,特别对于运行Android的移动设备来说,因为设备的资源比较宝贵,所以建议还是采用SAX来解析XML文件,当然,如果XML文件的内容比较小采用DOM是可行的。


Java代码 
  1. import java.io.InputStream;  
  2. import java.util.ArrayList;  
  3. import java.util.List;  
  4.   
  5. import javax.xml.parsers.DocumentBuilder;  
  6. import javax.xml.parsers.DocumentBuilderFactory;  
  7.   
  8. import org.w3c.dom.Document;  
  9. import org.w3c.dom.Element;  
  10. import org.w3c.dom.Node;  
  11. import org.w3c.dom.NodeList;  
  12.   
  13.   
  14. /** 
  15.  * 使用Dom解析xml文件 
  16.  * 
  17.  */  
  18. public class DomXMLReader {  
  19.   
  20. public static List<Person> readXML(InputStream inStream) {  
  21.     List<Person> persons = new ArrayList<Person>();  
  22.     DocumentBuilderFactory factory =  DocumentBuilderFactory.newInstance();  
  23.     try {  
  24.         DocumentBuilder builder = factory.newDocumentBuilder();  
  25.         Document dom = builder.parse(inStream);  
  26.         Element root = dom.getDocumentElement();  
  27.         NodeList items = root.getElementsByTagName("person");  
  28.         //查找所有person节点  
  29.       for (int i = 0; i < items.getLength(); i++) {  
  30.                 Person person = new Person();  
  31.                 //得到第一个person节点  
  32.           Element personNode = (Element) items.item(i);  
  33.                 //获取person节点的id属性值  
  34.           person.setId(new Integer(personNode.getAttribute("id")));  
  35.                 //获取person节点下的所有子节点(标签之间的空白节点和name/age元素)  
  36.                 NodeList childsNodes = personNode.getChildNodes();  
  37.                 for (int j = 0; j < childsNodes.getLength(); j++) {  
  38.                   Node node = (Node) childsNodes.item(j);               
  39.                   //判断是否为元素类型  
  40.             if(node.getNodeType() == Node.ELEMENT_NODE){                         
  41.                     Element childNode = (Element) node;  
  42.                     //判断是否name元素  
  43.               if ("name".equals(childNode.getNodeName())) {  
  44.                     //获取name元素下Text节点,然后从Text节点获取数据              person.setName(childNode.getFirstChild().getNodeValue());  
  45.                       } else if (“age”.equals(childNode.getNodeName())) {  
  46.                         person.setAge(new Short(childNode.getFirstChild().getNodeValue()));  
  47.                       }  
  48.                    }  
  49.                 }  
  50.             persons.add(person);  
  51.         }  
  52.         inStream.close();  
  53.     } catch (Exception e) {  
  54.         e.printStackTrace();  
  55.     }  
  56.     return persons;  
  57. }  

 

 

 

 

 

 

3.     Dom开发小技巧

1)         快速获得一个简单XML中的某项数据,改方法只适用于某个属性在DOM中只存在一个

 

Java代码 
  1. public static String getValByTagName(Document doc, String tagName) {  
  2.   NodeList list = doc.getElementsByTagName(tagName);  
  3.   if (list.getLength() > 0) {  
  4.     Node node = list.item(0);  
  5.     Node valNode = node.getFirstChild();  
  6.     if (valNode != null) {  
  7.       String val = valNode.getNodeValue();  
  8.       return val;  
  9.     }  
  10.   }  
  11.   return null;  
  12. }  

 

2)      快速的将数据列表转换成对象列表

如上述基本使用中的XML例子,先建立一个和XML对应的类,属性名称必须与XML中的名称一致,如:

Java代码 
  1. public class Person(){  
  2.   private String name;  
  3.   private String age;  
  4.   public void setName(String name){  
  5.     this.name = name;  
  6.   }  
  7.   public String getName(){  
  8.     return name;  
  9.   }  
  10.   public void setAge(String age){  
  11.     this.age = age;  
  12.   }  
  13.   public String getAge(){  
  14.     return age;  
  15.   }  
  16. }  

  

然后采用映射机制

 

Java代码 
  1. NodeList nodeList = doc.getElementsByTagName("person");  
  2. int len = nodeList.getLength();  
  3. for (int i = 0; i < len; i++) {  
  4.   Node node = nodeList.item(i);  
  5.   Person bean = (Person) convertToBean(Person.class, node);  
  6. }  
  7.   
  8. public static Object convertToBean(Class clazz, Node ele) {  
  9.   Object object = null;  
  10.   try {  
  11.     object = clazz.newInstance();  
  12.     Class[] parameterTypes = new Class[] { String.class };  
  13.     NodeList list = ele.getChildNodes();  
  14.     int len = list.getLength();  
  15.     for (int i = 0; i < len; i++) {  
  16.       try {  
  17.         Node node = list.item(i);  
  18.         String nodeName = node.getNodeName();  
  19.         String nodeVal = "";  
  20.         Node valueNode = node.getFirstChild();  
  21.         if (valueNode != null) {  
  22.           nodeVal = valueNode.getNodeValue();  
  23.         }  
  24.         Object[] arguments = new Object[] { nodeVal };  
  25.         if (nodeName.length() > 0) {  
  26.           String first = nodeName.substring(01);  
  27.           String last = nodeName.substring(1);  
  28.           Method method = clazz.getMethod("set" + first.toUpperCase() + last, parameterTypes);  
  29.           method.invoke(object, arguments);  
  30.         }  <li sty

使用sax方式解析

 基础知识:

     这种方式解析是一种基于事件驱动的api,有两个部分,解析器和事件处理器,解析器就是XMLReader接口,负责读取XML文档,和向事件处理器发送事件(也是事件源),事件处理器ContentHandler接口,负责对发送的事件响应和进行XML文档处理。

     下面是ContentHandler接口的常用方法

     public abstract void characters (char[] ch, int start, int length)

      这个方法来接收字符块通知,解析器通过这个方法来报告字符数据块,解析器为了提高解析效率把读到的所有字符串放到一个字符数组(ch)中,作为参数传递给character的方法中,如果想获取本次事件中读取到的字符数据,需要使用start和length属性。

    public abstract void startDocument () 接收文档开始的通知

     public abstract void endDocument () 接收文档结束的通知

    public abstract void startElement (String uri, String localName, String qName, Attributes atts) 接收文档开始的标签

    public abstract void endElement (String uri, String localName, String qName) 接收文档结束的标签

    在一般使用中为了简化开发,在org.xml.sax.helpers提供了一个DefaultHandler类,它实现了ContentHandler的方法,我们只想继承DefaultHandler方法即可。

   另外SAX解析器提供了一个工厂类:SAXParserFactory,SAX的解析类为SAXParser 可以调用它的parser方法进行解析。

   看了些基础以后开始上代码吧(核心代码,下载代码在附件)

复制代码
 1 public class SAXPraserHelper extends DefaultHandler {
2
3 final int ITEM = 0x0005;
4
5 List<channel> list;
6 channel chann;
7 int currentState = 0;
8
9 public List<channel> getList() {
10 return list;
11 }
12
13 /*
14 * 接口字符块通知
15 */
16 @Override
17 public void characters(char[] ch, int start, int length)
18 throws SAXException {
19 // TODO Auto-generated method stub
20 // super.characters(ch, start, length);
21 String theString = String.valueOf(ch, start, length);
22 if (currentState != 0) {
23 chann.setName(theString);
24 currentState = 0;
25 }
26 return;
27 }
28
29 /*
30 * 接收文档结束通知
31 */
32 @Override
33 public void endDocument() throws SAXException {
34 // TODO Auto-generated method stub
35 super.endDocument();
36 }
37
38 /*
39 * 接收标签结束通知
40 */
41 @Override
42 public void endElement(String uri, String localName, String qName)
43 throws SAXException {
44 // TODO Auto-generated method stub
45 if (localName.equals("item"))
46 list.add(chann);
47 }
48
49 /*
50 * 文档开始通知
51 */
52 @Override
53 public void startDocument() throws SAXException {
54 // TODO Auto-generated method stub
55 list = new ArrayList<channel>();
56 }
57
58 /*
59 * 标签开始通知
60 */
61 @Override
62 public void startElement(String uri, String localName, String qName,
63 Attributes attributes) throws SAXException {
64 // TODO Auto-generated method stub
65 chann = new channel();
66 if (localName.equals("item")) {
67 for (int i = 0; i < attributes.getLength(); i++) {
68 if (attributes.getLocalName(i).equals("id")) {
69 chann.setId(attributes.getValue(i));
70 } else if (attributes.getLocalName(i).equals("url")) {
71 chann.setUrl(attributes.getValue(i));
72 }
73 }
74 currentState = ITEM;
75 return;
76 }
77 currentState = 0;
78 return;
79 }
80 }
复制代码
复制代码
 1 private List<channel> getChannelList() throws ParserConfigurationException, SAXException, IOException
2 {
3 //实例化一个SAXParserFactory对象
4 SAXParserFactory factory=SAXParserFactory.newInstance();
5 SAXParser parser;
6 //实例化SAXParser对象,创建XMLReader对象,解析器
7 parser=factory.newSAXParser();
8 XMLReader xmlReader=parser.getXMLReader();
9 //实例化handler,事件处理器
10 SAXPraserHelper helperHandler=new SAXPraserHelper();
11 //解析器注册事件
12 xmlReader.setContentHandler(helperHandler);
13 //读取文件流
14 InputStream stream=getResources().openRawResource(R.raw.channels);
15 InputSource is=new InputSource(stream);
16 //解析文件
17 xmlReader.parse(is);
18 return helperHandler.getList();
19 }
复制代码

从第二部分代码,可以看出使用SAX解析XML的步骤:

1、实例化一个工厂SAXParserFactory

2、实例化SAXPraser对象,创建XMLReader 解析器

3、实例化handler,处理器

4、解析器注册一个事件

4、读取文件流

5、解析文件



上图为最终效果图。

代码结构示意图:

我们先来看看代码:

main.xml

[xhtml]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     >  
  7. <TextView  
  8.     android:id="@+id/showBeauty"    
  9.     android:layout_width="fill_parent"   
  10.     android:layout_height="wrap_content"   
  11.     />  
  12. </LinearLayout>  

Activity的代码

[java]  view plain copy
  1. package cn.com.pulltest;  
  2.   
  3. import java.io.InputStream;  
  4. import java.util.ArrayList;  
  5.   
  6. import org.xmlpull.v1.XmlPullParser;  
  7. import org.xmlpull.v1.XmlPullParserFactory;  
  8.   
  9. import android.app.Activity;  
  10. import android.os.Bundle;  
  11. import android.util.Log;  
  12. import android.widget.TextView;  
  13.   
  14. public class PullActivity extends Activity {  
  15.     private String result = "";  
  16.     private ArrayList<Beauty> beauties = new ArrayList();  
  17.     @Override  
  18.     public void onCreate(Bundle savedInstanceState) {  
  19.         super.onCreate(savedInstanceState);  
  20.         setContentView(R.layout.main);  
  21.         try {  
  22.             // 以流的形式获取src目录下的xml文件(此文件的父亲文件夹必须是src)  
  23.             InputStream InputStream =  this.getClass().getClassLoader().getResourceAsStream("beauties.xml");  
  24.             // 获取一个XmlPullParser  
  25.             XmlPullParserFactory xmlPullParserFactory = XmlPullParserFactory.newInstance();  
  26.             XmlPullParser parser = xmlPullParserFactory.newPullParser();  
  27.             // 设置输入流已经编码方式  
  28.             parser.setInput(InputStream, "UTF-8");  
  29.             // 获取当前的事件类型  
  30.             int eventType = parser.getEventType();  
  31.             Beauty beauty = null;  
  32.             while(XmlPullParser.END_DOCUMENT!=eventType){  
  33.                 String nodeName = parser.getName();  
  34.                   
  35.                 switch (eventType) {  
  36.                 case XmlPullParser.START_TAG:  
  37.                     if(nodeName.equals("beauty")){  
  38.                         beauty = new Beauty();  
  39.                     }  
  40.                     if(nodeName.equals("name")){  
  41.                         beauty.setName(parser.nextText());  
  42.                     }  
  43.                     if(nodeName.equals("age")){  
  44.                         beauty.setAge(parser.nextText());  
  45.                     }  
  46.                     break;  
  47.                   
  48.                 case XmlPullParser.END_TAG:  
  49.                     if(nodeName.equals("beauty")&&beauty!=null){  
  50.                         beauties.add(beauty);  
  51.                     }  
  52.                       
  53.                     break;  
  54.                 default:  
  55.                     break;  
  56.                 }  
  57.                 // 手动的触发下一个事件  
  58.                 eventType = parser.next();  
  59.                 Log.i("PullActivity", eventType+"");  
  60.             }  
  61.               
  62.             for(Beauty beauty2 : beauties){  
  63.                 result+="/n"+beauty2.toString();  
  64.             }  
  65.             //result = beauties.size()+"";  
  66.             TextView textView = (TextView) findViewById(R.id.showBeauty);  
  67.             textView.setText("最终结果: /n "+result);  
  68.               
  69.               
  70.         } catch (Exception e) {  
  71.             e.printStackTrace();  
  72.         }  
  73.           
  74.           
  75.     }  
  76.     /** 
  77.      *  
  78.      * @author chenzheng 
  79.      * 这里使用内部类是为了效率考虑,内部类要比单独顶一个bean类更加的高效以及节约空间 
  80.      * 
  81.      */  
  82.     private class Beauty{  
  83.         String name;  
  84.         String age;  
  85.         public String getName() {  
  86.             return name;  
  87.         }  
  88.         public void setName(String name) {  
  89.             this.name = name;  
  90.         }  
  91.         public String getAge() {  
  92.             return age;  
  93.         }  
  94.         public void setAge(String age) {  
  95.             this.age = age;  
  96.         }  
  97.         @Override  
  98.         public String toString() {  
  99.             return "美女资料 [年龄=" + age + ", 姓名=" + name + "]";  
  100.         }   
  101.           
  102.           
  103.           
  104.     }  
  105.       
  106.       
  107. }  

 

beauties.xml

[xhtml]  view plain copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2.   
  3. <beauties>  
  4.   
  5.     <beauty>  
  6.   
  7.         <name>林志玲</name>  
  8.   
  9.         <age>28</age>  
  10.   
  11.     </beauty>  
  12.   
  13.     <beauty>  
  14.   
  15.         <name>杨幂</name>  
  16.   
  17.         <age>23</age>  
  18.   
  19.     </beauty>  
  20.   
  21. </beauties>  

这里的book.xml没有用到。

AndroidManifest.xml使用的是默认的。

运行,我们就可以看到了刚开始的那种结果了。

 

----------------------------------------------------------------------------------------

 

     这里对xml进行解析时,需要注意的是,beauties.xml的位置,我们这里多添加了一个book.xml也是为了让大家明白,xml文件的确切位置应该是在src下,而不是src下的子文件夹下。

 

   

----------------------------------------------------------------------------------------

      一般,我们使用java解析xml,主要还是有两种方式,一种方式是SAX解析,另一种是DOM解析。当然还有一系列的其他第三方解析API,如JDOM/DOM4J.他们各自有各自的优缺点。这里我们主要分析下最基础的两种解析方式,sax解析和dom解析。

      两者依赖的解析机制是完全不同的。sax解析,依赖于事件触发机制,你可以认为我们在读取xml的时候,每遇到一个xml内容都会触发相应的事件,我们一行行的往下读,事件也自动的一个个的往下触发,一直到最终结束。代码中,我们则需要实现一个defaultHandler,来定义当xml读到什么内容时,进行什么样子的操作。sax解析,只能从文档头一直读到尾,中间不能停止也不能对文件进行修改。直到解析完了整个文档才会返回。

     dom解析,则是通过在内存中形成一个节点树来完成xml解析,它虽然可以快速的定位xml中的某个位置,并且可以对其进行修改操作,但是它对内存的要求比较大。特别是当xml文件比较大的时候,这个缺点就更严重了。对于手机来说,这很致命。

     SAX方式的特点是需要解析完整个文档才会返回,如果在一个XML文档中我们只需要前面一部分数据,但是使用SAX方式还是会对整个文档进行解析,尽管XML文档中后面的大部分数据我们其实都不需要解析,因此这样实际上就浪费了处理资源。

     为了解决点这种缺陷,Android利用另一种更加高效方便的xml解析方式对xml文件进行解析,这就是Pull解析。

      Pull解析器和SAX解析器虽有区别但也有相似性。他们的区别为:SAX解析器的工作方式是自动将事件推入注册的事件处理器进行处理,因此你不能控制事件的处理主动结束;而Pull解析器的工作方式允许你在应用程序代码中主动从解析器中获取事件,正因为是主动获取事件,因此可以在满足了需要的条件后不再获取事件,结束解析

    

       OPhone/Android系统中和Pull方式相关的包为org.xmlpull.v1,在这个包中提供了Pull解析器的工厂类XmlPullParserFactory和Pull解析器XmlPullParser,XmlPullParserFactory实例调用newPullParser方法创建XmlPullParser解析器实例,接着XmlPullParser实例就可以调用getEventType()和next()等方法依次主动提取事件,并根据提取的事件类型进行相应的逻辑处理。

    代码如下

[java]  view plain copy
  1. // 以流的形式获取src目录下的xml文件(此文件的父亲文件夹必须是src)  
  2.             InputStream InputStream =  this.getClass().getClassLoader().getResourceAsStream("beauties.xml");  
  3.             // 获取一个XmlPullParser  
  4.             XmlPullParserFactory xmlPullParserFactory = XmlPullParserFactory.newInstance();  
  5.             XmlPullParser parser = xmlPullParserFactory.newPullParser();  
  6.             // 设置输入流已经编码方式  
  7.             parser.setInput(InputStream, "UTF-8");  

我们然后就可以通过XmlPullParser里面提供的方法进行解析了,这里列出几个重要的方法说明

//在xml读取的开始调用,并触发读取文件时的第一个事件,返回的是事件的标示 

public int getEventType() throws XmlPullParserException ;  

//遍历下一个事件,返回一个事件的类型  

public int next() throws XmlPullParserException, IOException  

//得到当前Tag名字  

public String getName();  

//获取文本  

public String getText();  

  

//得到当前Tag下面的属性数量  

public int getAttributeCount() ;  

//得到当前Tag下面指定位置的属性名称  

public String getAttributeName(int index);  

  

//得到当前Tag下面指定位置的属性植  

public String getAttributeValue(int index);  

 

//如果当前事件是一个start_tag并且下一个元素就是文本的话,那么就将这个文本内容返回;如果下一个元素直接就是end_tag的话,那么久返回空字符串;其他情况返回异常。

public String getNextText();

-------------------------------------------------------------------------

我们总结下pull解析的代码步骤:

第一步:我们需要先定义一个xml文件(当然也可以是从网络上获取的xml文件)

第二步:创建一个XmlPullParser对象,用于对文件进行解析

第三步:通过parser.setInput()方法,将文件和文件解析器关联起来。

第四步:调用getEventType();方法正式开始解析。

第五步:在while循环中处理xml

 

JSON是JavaScript Object Notation的缩写,可见JSON来源于JavaScript。JSON数据是一系列键值对的集合。

JSON和XML的比较

  • JSON比XML体积小
  • JSON和JavaScript交互更加方便
  • JSON对数据的描述性没有XML好
  • JSON的速度要远远大于XML
  • JSON的解析要比XML的解析要方便

JSON已经被大多数开发人员所接受,在网络数据的传输当中应用非常广泛


下面的代码就是一个JSON:

[plain]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. {    
  2. "phone" : ["12345678", "87654321"], // 数组    
  3. "name" : "tianjiefeng", // 字符串    
  4. "age" : 100, // 数值    
  5. "address" : { "country" : "china", "province" : "jiangsu" }, // JSON对象    
  6. "married" : false // 布尔值    
  7. }  
JSON是以key/value的形式存在的,key是Strng类型的,value的类型可以是一个数组,可以是一个字符串,可以是一个数值,也可以是一个布尔值,甚至可以是一个JSON对象


一、JSONObject的创建

我们先来看一个Demo,把上面的JSON对象创建出来,并且写入存储卡文件

既然要写入存储卡,那么就必须在AndroidManifest.xml中加入一下权限

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />  

接着在JSONCreateDemoActivity.java里面编写如下代码:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.tianjf;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileNotFoundException;  
  5. import java.io.FileOutputStream;  
  6. import java.io.PrintStream;  
  7.   
  8. import org.json.JSONArray;  
  9. import org.json.JSONException;  
  10. import org.json.JSONObject;  
  11.   
  12. import android.app.Activity;  
  13. import android.os.Bundle;  
  14. import android.os.Environment;  
  15.   
  16. public class JSONCreateDemoActivity extends Activity {  
  17.     @Override  
  18.     public void onCreate(Bundle savedInstanceState) {  
  19.         super.onCreate(savedInstanceState);  
  20.         setContentView(R.layout.main);  
  21.   
  22.         // 判断sdcard存不存在,不存在不操作  
  23.         if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {  
  24.             // 返回到程序的被调用出  
  25.             return;  
  26.         }  
  27.   
  28.         // 将JSON对象写入存储卡  
  29.         writeJSONObjectToSdCard(createJSONObject());  
  30.     }  
  31.   
  32.     // 创建以下的JSON对象  
  33.     // {  
  34.     // "phone" : ["12345678", "87654321"], // 数组  
  35.     // "name" : "tianjiefeng", // 字符串  
  36.     // "age" : 100, // 数值  
  37.     // "address" : { "country" : "china", "province" : "jiangsu" }, // JSON对象  
  38.     // "married" : false // 布尔值  
  39.     // }  
  40.     private JSONObject createJSONObject() {  
  41.         // 最外层是{},也就是一个JSONObject对象  
  42.         JSONObject person = new JSONObject();  
  43.         try {  
  44.             // 第1个value是[ ],也就是一个JSONArray对象  
  45.             JSONArray phone = new JSONArray();  
  46.             phone.put("12345678");  
  47.             phone.put("87654321");  
  48.             person.put("phone", phone);  
  49.             // 第2个value一个字符串  
  50.             person.put("name""tianjiefeng");  
  51.             // 第3个value一个字符串数值  
  52.             person.put("age"100);  
  53.             // 第4个value一个JSONObject对象  
  54.             JSONObject address = new JSONObject();  
  55.             address.put("country""china");  
  56.             address.put("province""jiangsu");  
  57.             person.put("address", address);  
  58.             // 第5个value一个布尔值  
  59.             person.put("married"false);  
  60.         } catch (JSONException e) {  
  61.             e.printStackTrace();  
  62.         }  
  63.         return person;  
  64.     }  
  65.   
  66.     /** 
  67.      * 将JSON对象写入存储卡 
  68.      *  
  69.      * @param person 
  70.      * @throws FileNotFoundException 
  71.      */  
  72.     private void writeJSONObjectToSdCard(JSONObject person) {  
  73.         File file = new File(Environment.getExternalStorageDirectory() + File.separator + "json"  
  74.                 + File.separator + "json.txt");  
  75.         // 文件夹不存在的话,就创建文件夹  
  76.         if (!file.getParentFile().exists()) {  
  77.             file.getParentFile().mkdirs();  
  78.         }  
  79.         // 写入内存卡  
  80.         PrintStream outputStream = null;  
  81.         try {  
  82.             outputStream = new PrintStream(new FileOutputStream(file));  
  83.             outputStream.print(person.toString());  
  84.         } catch (FileNotFoundException e) {  
  85.             e.printStackTrace();  
  86.         } finally {  
  87.             if (outputStream != null) {  
  88.                 outputStream.close();  
  89.             }  
  90.         }  
  91.     }  
  92. }  

运行一下,打开File Explorer视图,打开mnt - sdcard - json目录,将里面的json.txt导出到计算机里面,就可以看到JSON对象以字符串的形式成功写入到了json.txt文件中


二、JSONObject的解析

直接将字符串转化为JSONObject对象来解析的Demo

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.tianjf;  
  2.   
  3. import java.util.HashMap;  
  4. import java.util.Map;  
  5.   
  6. import org.json.JSONException;  
  7. import org.json.JSONObject;  
  8.   
  9. import android.app.Activity;  
  10. import android.os.Bundle;  
  11. import android.util.Log;  
  12.   
  13. public class JSONParseDemoActivity extends Activity {  
  14.   
  15.     private static final String JSONString = "{" + "\"phone\":[\"12345678\",\"87654321\"],"  
  16.             + "\"name\":\"tianjiefeng\"," + "\"age\":100,"  
  17.             + "\"address\":{\"country\":\"china\",\"province\":\"jiangsu\"},"  
  18.             + "\"married\":false" + "}";  
  19.   
  20.     @Override  
  21.     public void onCreate(Bundle savedInstanceState) {  
  22.         super.onCreate(savedInstanceState);  
  23.         setContentView(R.layout.main);  
  24.   
  25.         // 解析得到一个Map对象  
  26.         Map<String, Object> personMap = parseJSONString(JSONString);  
  27.         Log.d("debug",  
  28.                 "phone:" + personMap.get("phone") + "\n" + "name:" + personMap.get("name") + "\n"  
  29.                         + "age:" + personMap.get("age") + "\n" + "address:"  
  30.                         + personMap.get("address") + "\n" + "married:" + personMap.get("married"));  
  31.     }  
  32.   
  33.     /** 
  34.      * JSON解析 
  35.      *  
  36.      * @param JSONString 
  37.      * @return 
  38.      */  
  39.     private Map<String, Object> parseJSONString(String JSONString) {  
  40.         Map<String, Object> resultMap = new HashMap<String, Object>();  
  41.         try {  
  42.             // 直接把JSON字符串转化为一个JSONObject对象  
  43.             JSONObject person = new JSONObject(JSONString);  
  44.             // 第1个键值对  
  45.             resultMap.put("phone", person.getJSONArray("phone").toString());  
  46.             // 第2个键值对  
  47.             resultMap.put("name", person.getString("name"));  
  48.             // 第3个键值对  
  49.             resultMap.put("age", person.getInt("age"));  
  50.             // 第4个键值对  
  51.             resultMap.put("address", person.getJSONObject("address").toString());  
  52.             // 第5个键值对  
  53.             resultMap.put("married", person.getBoolean("married"));  
  54.         } catch (JSONException e) {  
  55.             e.printStackTrace();  
  56.         }  
  57.         return resultMap;  
  58.     }  
  59. }  

运行之后打印出来的Log如下


用JsonReader来读取JSON字符串的内容

打开Android帮助文档找到JsonReader,会发现Since: API Level 11(3.0),也就是说3.0之前的SDK是没有JsonReader的。如果要对应3.0之前的版本,可以到Google的网站上去下载gson的jar包(URL:http://code.google.com/p/google-gson/downloads/list)。jar包导入项目的流程如下:

  1. 新建libs文件夹,把下载的jar包添加到libs文件夹中
  2. 右键gson-1.6.jar --> Build Path --> Add to Build Path(add操作之后就会看到Package视图下的Referenced Libraries下多了个gson-1.6.jar,说明jar包添加成功) 

添加好了jar包,我们就可以使用JsonReader了。具体代码如下

JSONUtils.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.tianjf;  
  2.   
  3. import java.io.StringReader;  
  4.   
  5. import com.google.gson.stream.JsonReader;  
  6.   
  7. public class JSONUtils {  
  8.     public void parseJson(String jsonData) {  
  9.         try {  
  10.             // 如果需要解析JSON数据,首要要生成一个JsonReader对象  
  11.             JsonReader reader = new JsonReader(new StringReader(jsonData));  
  12.             // 开始解析数组  
  13.             reader.beginArray();  
  14.             // 判断数组里面还有没下一个JSONObject对象  
  15.             while (reader.hasNext()) {  
  16.                 // 开始解析对象  
  17.                 reader.beginObject();  
  18.                 // 判断当前JSONObject对象里面还有没下一个键值对  
  19.                 while (reader.hasNext()) {  
  20.                     // 取出当前键值对的key  
  21.                     String tagName = reader.nextName();  
  22.                     // 取出key所对应的value  
  23.                     if (tagName.equals("name")) {  
  24.                         System.out.println("name--->" + reader.nextString());  
  25.                     } else if (tagName.equals("age")) {  
  26.                         System.out.println("age--->" + reader.nextInt());  
  27.                     }  
  28.                 }  
  29.                 // 结束解析对象  
  30.                 reader.endObject();  
  31.             }  
  32.             // 结束解析数组  
  33.             reader.endArray();  
  34.         } catch (Exception e) {  
  35.             e.printStackTrace();  
  36.         }  
  37.     }  
  38. }  

JSONParseDemoActivity.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.tianjf;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5.   
  6. public class JSONParseDemoActivity extends Activity {  
  7.   
  8.     private static final String JSONString = "[{\"name\":\"Michael\",\"age\":20},{\"name\":\"Mike\",\"age\":21}]";  
  9.   
  10.     @Override  
  11.     public void onCreate(Bundle savedInstanceState) {  
  12.         super.onCreate(savedInstanceState);  
  13.         setContentView(R.layout.main);  
  14.   
  15.         JSONUtils jsonUtils = new JSONUtils();  
  16.         jsonUtils.parseJson(JSONString);  
  17.     }  
  18. }  

这个例子是解析[{"name":"Michael","age":20},{"name":"Mike","age":21}]这个JSON字符串

先分析一下这个JSON字符串的结构:一个JSONArray里面有两个JSONObject

再分析一下JsonReader解析这个JSON字符串的流程:

  1. 遇到【[】,开始解析数组(reader.beginArray())
  2. 遇到【{】,开始解析对象(reader.beginObject())
  3. 遇到【"】,开始解析第一个键值对
  4. 遇到【"】,开始解析第二个键值对
  5. 遇到【}】,结束解析对象(reader.endObject())
  6. 遇到【{】,开始解析对象(reader.beginObject())
  7. 遇到【"】,开始解析第一个键值对
  8. 遇到【"】,开始解析第二个键值对
  9. 遇到【}】,结束解析对象(reader.endObject())
  10. 遇到【]】,结束解析数组(reader.endArray())


Gson类的fromJson方法自动解析并自动得到一个Entity对象,代码如下

User.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.tianjf;  
  2.   
  3. public class User {  
  4.     private String name ;  
  5.     private int age ;  
  6.     public String getName() {  
  7.         return name;  
  8.     }  
  9.     public void setName(String name) {  
  10.         this.name = name;  
  11.     }  
  12.     public int getAge() {  
  13.         return age;  
  14.     }  
  15.     public void setAge(int age) {  
  16.         this.age = age;  
  17.     }  
  18. }  

JSONUtils.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.tianjf;  
  2.   
  3. import com.google.gson.Gson;  
  4.   
  5. public class JSONUtils {  
  6.     public void parseUserFromJson(String jsonData) {  
  7.         Gson gson = new Gson();  
  8.         // Gson的fromJson方法是一 一对应的关系,自动将JSON的数据匹配到User对象中  
  9.         User user = gson.fromJson(jsonData, User.class);  
  10.         System.out.println("name--->" + user.getName());  
  11.         System.out.println("age---->" + user.getAge());  
  12.     }  
  13. }  

JSONParseDemoActivity.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.tianjf;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5.   
  6. public class JSONParseDemoActivity extends Activity {  
  7.   
  8.     private static final String JSONString = "{\"name\":\"Michael\",\"age\":20}";  
  9.   
  10.     @Override  
  11.     public void onCreate(Bundle savedInstanceState) {  
  12.         super.onCreate(savedInstanceState);  
  13.         setContentView(R.layout.main);  
  14.   
  15.         JSONUtils jsonUtils = new JSONUtils();  
  16.         jsonUtils.parseUserFromJson(JSONString);  
  17.     }  
  18. }  

上面的例子只有一个JSONObject对象,如果有多个对象怎么做到直接映射到一个User的List里面呢?代码如下

User.java

同上


JSONUtils.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.tianjf;  
  2.   
  3. import java.lang.reflect.Type;  
  4. import java.util.Iterator;  
  5. import java.util.LinkedList;  
  6.   
  7. import com.google.gson.Gson;  
  8. import com.google.gson.reflect.TypeToken;  
  9.   
  10. public class JSONUtils {  
  11.     public void parseUserFromJson(String jsonData) {  
  12.         Type listType = new TypeToken<LinkedList<User>>() {}.getType();  
  13.         Gson gson = new Gson();  
  14.         LinkedList<User> users = gson.fromJson(jsonData, listType);  
  15.         Iterator<User> iterator = users.iterator();  
  16.         while (iterator.hasNext()) {  
  17.             User user = (User) iterator.next();  
  18.             System.out.println("name--->" + user.getName());  
  19.             System.out.println("age---->" + user.getAge());  
  20.         }  
  21.     }  
  22. }  

JSONParseDemoActivity.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.tianjf;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5.   
  6. public class JSONParseDemoActivity extends Activity {  
  7.   
  8.     private static final String JSONString = "[{\"name\":\"Michael\",\"age\":20},{\"name\":\"Mike\",\"age\":21}]";  
  9.   
  10.     @Override  
  11.     public void onCreate(Bundle savedInstanceState) {  
  12.         super.onCreate(savedInstanceState);  
  13.         setContentView(R.layout.main);  
  14.   
  15.         JSONUtils jsonUtils = new JSONUtils();  
  16.         jsonUtils.parseUserFromJson(JSONString);  
  17.     }  
  18. }  


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值