下面是一個將XML轉換為JSON的示例,
通過SAX來解析XML,從而生成相應的JSON字符串
自我感覺還算是一個比較通用的 API ,主要包含3個類
1, ToJsonSAXHandler 類 繼承了 DefaultHandler 類,在解析
XML的過程中負責處理 SAX 事件。代碼如下:
Java代碼
package org.yjf.xmlToJson; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class ToJsonSAXHandler extends DefaultHandler { //jsonStringBuilder 保存解析XML時生成的json字符串 private StringBuilder jsonStringBuilder ; /* * isProcessing 表示 是否正在解析一個XML * startDocument 事件發生時設置 isProcessing = true * startDocument 事件發生時設置 isProcessing = false */ private boolean isProcessing; /* * justProcessStartElement 表示 是否剛剛處理完一個 startElement事件 * 引入這個標記的作用是為了判斷什麼時候輸出逗號 */ private boolean justProcessStartElement; public ToJsonSAXHandler(){ jsonStringBuilder = new StringBuilder(); } @Override public void startDocument() throws SAXException { /* * 開始解析XML文檔時 設定一些解析狀態 * 設置isProcessing為true,表示XML正在被解析 * 設置justProcessStartElement為true,表示剛剛沒有處理過 startElement事件 */ isProcessing = true; justProcessStartElement = true; //清空 jsonStringBuilder 中的字符 this.jsonStringBuilder.delete(0, this.jsonStringBuilder.length()); } @Override public void endDocument() throws SAXException { isProcessing = false; } @Override public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { /* * 是否剛剛處理完一個startElement事件 * 如果是 則表示這個元素是父元素的第一個元素 。 * 如果不是 則表示剛剛處理完一個endElement事件,即這個元素不是父元素的第一個元素 */ if(!justProcessStartElement){ jsonStringBuilder.append(','); justProcessStartElement = true; } jsonStringBuilder.append("{"); jsonStringBuilder.append("localName:").append('\"').append(localName).append('\"').append(','); jsonStringBuilder.append("uri:").append('\"').append(uri).append('\"').append(','); jsonStringBuilder.append("qName:").append('\"').append(qName).append('\"').append(','); //將解析出來的元素屬性添加到JSON字符串中 jsonStringBuilder.append("attrs:{"); if(attrs.getLength() > 0){ jsonStringBuilder.append(attrs.getLocalName(0)).append(":") .append(attrs.getValue(0)); for(int i = 1 ; i < attrs.getLength() ; i++){ jsonStringBuilder.append(',').append(attrs.getLocalName(i)).append(":") .append(attrs.getValue(i)); } } jsonStringBuilder.append("},"); //將解析出來的元素的子元素列表添加到JSON字符串中 jsonStringBuilder.append("childElements:[").append('\n'); } @Override public void endElement(String uri,String localName,String qName) throws SAXException { justProcessStartElement = false; jsonStringBuilder.append("]}").append('\n'); } @Override public void characters(char[] ch, int begin, int length) throws SAXException { /* * 是否剛剛處理完一個startElement事件 * 如果是 則表示這個元素是父元素的第一個元素 。 * 如果不是 則表示剛剛處理完一個endElement事件,即這個元素不是父元素的第一個元素 */ if(!justProcessStartElement){ jsonStringBuilder.append(','); }else justProcessStartElement = false; jsonStringBuilder.append('\"'); for(int i = begin ; i < begin+length ; i++){ switch(ch[i]){ case '\'':jsonStringBuilder.append("\\'");break; case '\"':jsonStringBuilder.append("\\\"");break; case '\n':jsonStringBuilder.append("\\n");break; case '\t':jsonStringBuilder.append("\\t");break; case '\r':jsonStringBuilder.append("\\r");break; default: jsonStringBuilder.append(ch[i]);break; } } jsonStringBuilder.append('\"').append('\n'); } public String getJsonString() throws XMLToJSONException{ if(this.isProcessing) throw new XMLToJSONException("getJsonString before resolution is finished"); else return jsonStringBuilder.toString(); } }
2,XMLToJSONException 是一個異常類(封裝在轉換過程中可能產生的異常),代碼如下:
Java代碼
package org.yjf.xmlToJson; public class XMLToJSONException extends Exception { private static final long serialVersionUID = 1L; public XMLToJSONException(){} public XMLToJSONException(String message){ super(message); } }
3,XMLToJSON 類 是一個將XML轉換為JSON字符串的工具類
Java代碼
package org.yjf.xmlToJson; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.StringReader; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.XMLReaderFactory; public class XMLToJSON { public static String convert(String xmlStr) throws SAXException, IOException, XMLToJSONException { return convert(new InputSource(new StringReader(xmlStr))); } public static String convert(File file) throws SAXException, IOException, XMLToJSONException { return convert(new InputSource(new FileInputStream(file))); } public static String convert(InputSource inputSource) throws SAXException, IOException, XMLToJSONException { ToJsonSAXHandler handler = new ToJsonSAXHandler(); //創建一個 SAX 解析器 ,並設置這個解析器的內容事件處理器 和 錯誤事件處理器 為 handler XMLReader reader = XMLReaderFactory.createXMLReader(); reader.setContentHandler(handler); reader.setErrorHandler(handler); //用 SAX 解析器解析XML輸入源 reader.parse(inputSource); //返回 ToJsonSAXHandler 中保存的 json字符串 return handler.getJsonString(); } }
測試類 Test 如下 (因為生成的JSON不包含縮進,所以看起來可能不太直觀,所以我用了JSONObject類來打印帶有縮進的JSON字符串,同時也驗證了轉換出來的JSON字符串是一個有效的JSON字符串):
Java代碼package test; import java.io.File; import java.io.IOException; import org.json.JSONException; import org.json.JSONObject; import org.xml.sax.SAXException; import org.yjf.xmlToJson.XMLToJSON; import org.yjf.xmlToJson.XMLToJSONException; public class Test_1 { public static void main(String[] args) throws JSONException, SAXException, IOException, XMLToJSONException{ String jsonStr = XMLToJSON.convert(new File("books.xml")); /* * JSONObject 是一個JSON對象的java實現 * 可以通過用一個有效的JSON字符串來構造JSON對象 * 下面的兩行代碼通過轉換而來的JSON字符串構造了一個JSON對象, * 並且打印出了這個JSON對象的帶有縮進的字符串表示 */ JSONObject jsonObj = new JSONObject(jsonStr); System.out.println(jsonObj.toString(2)); } }
books.xml 的內容如下:
<?xml version="1.0" encoding="utf-8"?> <books count="2" xmlns="http://test.org/books"> <book id="1" page="1000"> <name>Thinking in JAVA</name> </book> <book id="2" page="800"> <name>Core JAVA2</name> </book> </books>
運行 Test 類輸出的JSON字符串 如下:
{ "attrs": {"count": 2}, "childElements": [ "\n\t", { "attrs": { "id": 1, "page": 1000 }, "childElements": [ "\n\t\t", { "attrs": {}, "childElements": ["Thinking in JAVA"], "localName": "name", "qName": "name", "uri": "http://test.org/books" }, "\n\t" ], "localName": "book", "qName": "book", "uri": "http://test.org/books" }, "\n\t", { "attrs": { "id": 2, "page": 800 }, "childElements": [ "\n\t\t", { "attrs": {}, "childElements": ["Core JAVA2"], "localName": "name", "qName": "name", "uri": "http://test.org/books" }, "\n\t" ], "localName": "book", "qName": "book", "uri": "http://test.org/books" }, "\n" ], "localName": "books", "qName": "books", "uri": "http://test.org/books" }
參考於: http://www.iteye.com/topic/402083