1. 程式人生 > >XML與JSON格式資料解析方法

XML與JSON格式資料解析方法

    在網路上傳輸資料時最常用的格式有兩種:XML和JSON,下面就來學習如何解析XML和JSON格式的資料。

一、解析XML格式資料

XML格式內容如下:

<apps>
    <app>
        <id>1</id>
        <name>Google Maps</name>
        <version>1.0</version>
    </app>
    <app>
        <id>2</id>
        <name>Chrome</name>
        <version>2.1</version>
    </app>
    <app>
        <id>3</id>
        <name>Google Play</name>
        <version>2.3</version>
    </app>
</apps>

1.1 Pull方式解析

    解析XML格式的資料方法有很多,常用的兩種是Pull解析和SAX解析。Pull解析方法如下:

    private void parseXMLWithPull(String xmlData) {
        try {
            final XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            final XmlPullParser xmlPullParser = factory.newPullParser();
            xmlPullParser.setInput(new StringReader(xmlData));
            int eventType = xmlPullParser.getEventType();
            String id = "", name = "", version = "";
            while (eventType != XmlPullParser.END_DOCUMENT) {
                String nodeName = xmlPullParser.getName();
                switch (eventType) {
                    // 開始解析某個節點
                    case XmlPullParser.START_TAG: {
                        if ("id".equals(nodeName)) {
                            id = xmlPullParser.nextText();
                        }
                        else if ("name".equals(nodeName)) {
                            name = xmlPullParser.nextText();
                        }
                        else if ("version".equals(nodeName)) {
                            version = xmlPullParser.nextText();
                        }
                        break;
                    }
                    // 完成解析某個節點
                    case XmlPullParser.END_TAG: {
                        if ("app".equals(nodeName)) {
                            Log.d("MainActivity", "id is " + id);
                            Log.d("MainActivity", "name is " + name);
                            Log.d("MainActivity", "version is " + version);
                        }
                        break;
                    }
                    default:
                        break;
                }
                eventType = xmlPullParser.next();
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    首先通過XmlPullParserFactory的例項獲得到XmlPullPaser物件,然後呼叫XmlPullParser的setInput()方法將伺服器返回的XML資料設定進去就可以開始解析了。解析過程也非常簡單,通過getEventType()方法可以得到當前的解析事件,然後在體格while迴圈中不斷進行解析,如果當前的解析事件不等於XmlPullParser.END_DOCUMENT,說明解析工作還沒有完成,呼叫next()方法可以獲取下一個解析事件。

    在while迴圈中,通過getName()方法得到當前節點的名字,如果發現節點名等於id、name或version,就呼叫nextText()方法來獲取節點的具體內容,每當解析完成一個app節點後就將獲取到的內容打印出來。

1.2 SAX方式解析

    使用SAX方式解析,通常情況下,會新建一個類繼承自DefaultHandler,並重寫父類的五個方法,如下所示:

public class SAXHandler extends DefaultHandler {

    private String nodeName;

    private StringBuilder id;
    private StringBuilder name;
    private StringBuilder version;

    @Override
    public void startDocument() throws SAXException {
        //super.startDocument();
        id = new StringBuilder();
        name = new StringBuilder();
        version = new StringBuilder();
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        //super.startElement(uri, localName, qName, attributes);
        // 記錄當前節點名
        nodeName = localName;
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        //super.characters(ch, start, length);
        // 根據節點名判斷將內容新增到哪一個StringBuilder
        if ("id".equals(nodeName)) {
            id.append(ch, start, length);
        }
        else if ("name".equals(nodeName)) {
            name.append(ch, start, length);
        }
        else if ("version".equals(nodeName)) {
            version.append(ch, start, length);
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        //super.endElement(uri, localName, qName);
        if ("app".equals(localName)) {
            Log.d("MainActivity", "id is " + id.toString().trim());
            Log.d("MainActivity", "name is " + name.toString().trim());
            Log.d("MainActivity", "version is " + version.toString().trim());
        }
        // 最後要將StringBuilder清空掉
        id.setLength(0);
        name.setLength(0);
        version.setLength(0);
    }

    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
    }
}
    接下來修改MainActivity中的程式碼,如下所示:
    private void parseXMLWithSAX(String xmlData){
        try 
        {
            final SAXParserFactory factory = SAXParserFactory.newInstance();
            final XMLReader xmlReader = factory.newSAXParser().getXMLReader();
            final SAXHandler handler = new SAXHandler();
            // 將SAXHandler的例項設定到XMLReader中
            xmlReader.setContentHandler(handler);
            // 開始解析執行
            xmlReader.parse(new InputSource(new StringReader(xmlData)));
        } 
        catch (Exception e) 
        {
            e.printStackTrace();
        }
    }

二、解析JSON格式資料

    比起XML格式,JSON格式的主要優勢在於它的體積更小,在網路上傳輸的時候可以更省流量。但缺點在於,它的語義性較差,看起來不如XML直觀。

    JSON格式的內容如下:

[{"id":"5","version":"5.5","name":"Clash of Clans"},
{"id":"6","version":"7.0","name":"Boom Beach"},
{"id":"7","version":"3.5","name":"Clash Royale"}]

2.1 使用JSONObject

    類似地,解析JSON資料也有很多方法,可以使用官方提供的JSONObject,也可以使用谷歌的開源庫GSON。JSONObject解析方法如下:

    private void parseJSONWithJSONObject(String jsonData) {
        try {
            final JSONArray jsonArray = new JSONArray(jsonData);
            for (int i = 0; i < jsonArray.length(); i++) {
                final JSONObject jsonObject = jsonArray.getJSONObject(i);
                String id = jsonObject.getString("id");
                String name = jsonObject.getString("name");
                String version = jsonObject.getString("version");
                Log.d("MainActivity", "id is " + id);
                Log.d("MainActivity", "name is " + name);
                Log.d("MainActivity", "version is " + version);
            }
        }
        catch (JSONException e) {
            e.printStackTrace();
        }
    }

    很容易看出,解析JSON的程式碼真的非常簡單,首先將伺服器返回的資料傳入到一個JSONArray物件中。然後遍歷這個JSONArray,從中取出每一個元素都是JSONObject的物件,只需要呼叫getString()方法就可以將這些資料取出。

2.2 使用GSON

    想要使用GSON,必須先新增GSON庫的依賴,編輯app/build.gradle檔案,在dependencies閉包中新增如下內容:

compile 'com.google.code.gson:gosn:2.7'

    GSON可以將一段JSON格式的字串自動對映成一個物件,從而不需要我們再手動去編寫程式碼進行解析了。

    首先新建App類,並加入id、name和version這3個欄位,如下所示:

public class App {

    private String id;

    private String name;

    private String version;

    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getVersion() {
        return version;
    }
    public void setVersion(String version) {
        this.version = version;
    }
}
    修改MainActivy中的程式碼,如下所示:
    private void parseJSONWithGSON(String jsonData) {
        final Gson gson = new Gson();
        List<App> appList = gson.fromJson(jsonData, new TypeToken<List<App>>() {}.getType());
        for (App app : appList) {
            Log.d("MainActivity", "id is " + app.getId());
            Log.d("MainActivity", "name is " + app.getName());
            Log.d("MainActivity", "version is " + app.getVersion());
        }
    }