在网上搜了一圈,
发现XML和
JSON的互转都需要引入一些开源的jar包,可能国外的大拿提供的代码更加完善,功能更多,但是我不需要那么复杂的功能,于是自己写了一版,能进行简单的转换,支持带属性多层级的xml(json),分享给大家。
class="java" name="code">
package com.transformer.plugin.utility;
/**
* Author: Xu Xin
* 使用原生jdk 实现的json和xml互转
*/
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class XMLJson {
// xml 转json
public static String x2j(String xml) throws Exception{
Document doc = DocumentHelper.parseText(xml);
String result = parseNode(doc);
return result;
}
//json转xml
public static String j2x(String json) throws Exception{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document doc = factory.newDocumentBuilder().newDocument();
parseJson(json,doc);
return DocumentHelper.asXML(doc);
}
//将XML DOM的节点解析为json字符串
private static String parseNode(Node n){
String result = "";
StringBuffer sb = new StringBuffer();
int num = 0;
if(n.hasAttributes()){
for (int i=0;i<n.getAttributes().getLength();i++){
Node attr = n.getAttributes().item(i);
if(num>0) sb.append(",");
num++;
sb.append("\"@"+attr.getNodeName()+"\":\""+attr.getNodeValue()+"\"");
}
}
if (n.hasChildNodes()){
NodeList nl = n.getChildNodes();
for(int i=0;i<nl.getLength();i++){
Node child = nl.item(i);
if(num>0) sb.append(",");
num++;
if(child.getNodeType()==Node.ELEMENT_NODE) {
sb.append("\""+child.getNodeName()+"\":");
sb.append(parseNode(child));
}else if(child.getNodeType()==Node.TEXT_NODE){
sb.append((child.getNodeValue()==null||"".equals(child))?("[]"):("\""+child.getNodeValue()+"\""));
}
}
}else if (n.getNodeType()==Node.ELEMENT_NODE){
sb.append((n.getNodeValue()==null?("[]"):("\""+n.getNodeValue()+"\"")));
}
result = sb.toString();
if(num>1||n.getNodeType()==Node.DOCUMENT_NODE) result="{"+result+"}";
return result;
}
// 将json串解析为XML DOM节点
private static void parseJson(String json,Node parent) throws Exception {
Document doc ;
if(parent instanceof Document)
doc = (Document) parent;
else
doc = parent.getOwnerDocument();
// Node result = null;
if(json==null||"".equals(json)) throw new Exception("无json数据");
json = json.trim();
if(!json.startsWith("{")||!json.endsWith("}")) throw new Exception("json数据必须在{ }之间,而被解析的数据为:"+json);
String key = "";
Object value ;
boolean extractkey = false;
boolean extractvalue = false;
for(int i=1;i<json.length()-1;i++){
char cur_c = json.charAt(i);
if(extractkey){
if(cur_c!='"')
key+=cur_c;
else {
extractkey = false;
// System.out.println("Element Key:"+key);
}
}else if(extractvalue){
if(cur_c=='{'){
int left=1,right=0;
String subjson="{";
while(left>right){
i++;
cur_c = json.charAt(i);
subjson+=cur_c;
if(cur_c=='{'){
left++;
}else if(cur_c=='}'){
right++;
}
}
// System.out.println("Complex Element:"+subjson);
Element ele = doc.createElement(key);
parseJson(subjson, ele);
parent.appendChild(ele);
}else if(cur_c=='"'){
String sub = "";
i++;
cur_c=json.charAt(i);
while(cur_c!='"'){
sub+=cur_c;
i++;
cur_c = json.charAt(i);
}
// System.out.println("Text Element:"+sub);
if(key.startsWith("@")){
Element ele = (Element) parent;
Attr a = doc.createAttribute(key.substring(1));
a.setValue(sub);
ele.setAttributeNode(a);
}else{
Node n = doc.createElement(key);
n.setTextContent(sub);
parent.appendChild(n);
}
}else if(cur_c=='['){
if(key.startsWith("@")){
Element ele = (Element) parent;
ele.setAttribute(key.substring(0), "");
}else{
Node n = doc.createElement(key);
parent.appendChild(n);
}
while(cur_c!=']'){
i++;
}
i++;
// System.out.println("Empty Element");
}else if(cur_c==','){
extractvalue=false;
}
}else{
if(cur_c=='"'){
extractkey=true;
key = "";
}else if(cur_c==':'){
extractkey=false;
extractvalue = true;
}
}
}
}
public static void main(String[] args){
try {
String xml ="<Service><ServiceURL name=\"test\">url</ServiceURL><ServiceAction>action</ServiceAction>"
+ "<ServiceData><col1>a</col1><col2>b</col2><col3>c</col3></ServiceData></Service>";
String json = XMLJson.x2j(xml);
System.out.println(json);
System.out.println();
xml = XMLJson.j2x(json);
System.out.println(xml);
} catch(Exception e) {
e.printStackTrace();
}
}
}
在写完这篇文章的瞬间,我又发现一个问题,就是重复节点的处理,网上流行的json框架是把重复节点处理成一个数组,但是会丢掉key值,我的不会丢掉key值,但是体现不出序列,见仁见智吧,以后想好了再改。