`
yanfaguanli
  • 浏览: 655472 次
文章分类
社区版块
存档分类
最新评论

如何用Google APIs和Google的应用系统进行集成(7)----在把JSON转换成XML数据过程中,JSON数据中包含违背XML数据规范:XML节点名不能只是数字的Java解决方案

 
阅读更多

笔者在调用Google Calendar APIs的GetColors过程当中(具体关于Google Calendar API已经Google API的介绍请见我其他的博文,当前我们只是拿Google Calendar API返回的结果举一个例子),JSON返回的数据中,出现了以数字作为键(key)的数据;但是因为我们在企业应用集成中,有时候需要把JSON数据转换成XML数据;那么这个时候,JSON数据中的键(key)映射到XML数据中将成为XML数据的节点名字(Node Name),如果JSON中的键(key)是数字的话,映射到XML数据的时候就会出错,因为XML规范中不支持把纯粹的数字作为XML数据的节点名字;这种情况下,我们就需要在对JSON数据转换成XML数据之间,进行一下处理。

以Google 日历(Calendar) API中的获取颜色(Get Color)的数据为例子,请见下面的数据。Calendar键(key)中的值,是一个包含多个对象的对象;每个对象的键(key)是一个数字,而且数字呈现递增的趋势;同理Event键(key)中的值也有同样的特征;如果把这样的数据转换成XML的数据的话,转换将不会成功。

{
 "kind": "calendar#colors",
 "updated": "2012-02-14T00:00:00.000Z",
 "calendar": {
  "1": {
   "background": "#ac725e",
   "foreground": "#1d1d1d"
  },
  "2": {
   "background": "#d06b64",
   "foreground": "#1d1d1d"
  },
  "3": {
   "background": "#f83a22",
   "foreground": "#1d1d1d"
  }
 },
 "event": {
  "1": {
   "background": "#a4bdfc",
   "foreground": "#1d1d1d"
  },
  "2": {
   "background": "#7ae7bf",
   "foreground": "#1d1d1d"
  }
 }
}

比如,我们把上面的数据,在一个在线的JSON转XML的网站上进行转换,http://www.freeformatter.com/json-to-xml-converter.html,在这个在线工具里面将会提示下面的错误信息:



那么解决的办法是什么呢?解决的办法就是把上面的带有数字的键(key)值对集合,变成一个没有数字的键(key)的数组,如下面的格式,

{
"kind": "calendar#colors",
"updated": "2012-02-14T00:00:00.000Z",
"calendar": [{
 "background": "#ac725e",
 "foreground": "#1d1d1d"
 },
 {
 "background": "#d06b64",
 "foreground": "#1d1d1d"
 },
 {
 "background": "#f83a22",
 "foreground": "#1d1d1d"
 }
 ]
},
"event": [{
 "background": "#a4bdfc",
 "foreground": "#1d1d1d"
 },
 {
 "background": "#7ae7bf",
 "foreground": "#1d1d1d"
 }
 ]
}
}

转换后的XML的数据如下,

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <calendar>
      <element>
         <background>#ac725e</background>
         <foreground>#1d1d1d</foreground>
      </element>
      <element>
         <background>#d06b64</background>
         <foreground>#1d1d1d</foreground>
      </element>
      <element>
         <background>#f83a22</background>
         <foreground>#1d1d1d</foreground>
      </element>
   </calendar>
   <kind>calendar#colors</kind>
   <updated>2012-02-14T00:00:00.000Z</updated>
</root>

那么问题来,如果用代码自动来实现转换且不引入任何的除JDK自带的API之外的其他的jar包呢?具体算法,请见下面的代码。

1.NumberKeyPosition Java Bean: 用来存储数字键(key)在JSON字符串中出现的开始位置,结束位置,以及是否是第一个数字键(key),是否是最后一个数字数字键(key),比如上面的中下面的数据,是calendar的第一个,所以isFirstOne的值为True。

 "1": {
   "background": "#ac725e",
   "foreground": "#1d1d1d"
  }

public class NumberKeyPosition {

	private int startPos;
	private int endPos;
	private boolean isFirstOne=false;
	private boolean isLastOne=false;

	public int getStartPos() {
		return startPos;
	}

	public void setStartPos(int startPos) {
		this.startPos = startPos;
	}

	public int getEndPos() {
		return endPos;
	}

	public void setEndPos(int endPos) {
		this.endPos = endPos;
	}

	public boolean isFirstOne() {
		return isFirstOne;
	}

	public void setFirstOne(boolean isFirstOne) {
		this.isFirstOne = isFirstOne;
	}

	public boolean isLastOne() {
		return isLastOne;
	}

	public void setLastOne(boolean isLastOne) {
		this.isLastOne = isLastOne;
	}
}

2.CovertNumberKeyAsArrayUtil 类:这个类就是执行上面处理JSON数据的具体的执行算法的类了。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CovertNumberKeyAsArrayUtil {
	private String jsonString;
	public void setJsonString(String jsonString) {
		this.jsonString = jsonString;
	}
	public CovertNumberKeyAsArrayUtil(){
		
	}
	public CovertNumberKeyAsArrayUtil(String jsonString){
		this.jsonString=jsonString;
	}
	
	public String readFileAsString(String fileName){
		InputStream ins=this.getClass().getResourceAsStream(fileName);
		StringBuffer sBuffer=new StringBuffer();
		BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(ins));
		String lineString="";
		try {
			while((lineString=bufferedReader.readLine())!=null){
				sBuffer.append(lineString);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		//System.out.println(sBuffer.toString());
		return sBuffer.toString();
	}
	/**
	 * getNumberKeyPositions
	 * @param jsonString
	 * @return
	 */
	private List<NumberKeyPosition> getNumberKeyPositions(){
		List<NumberKeyPosition> lsNumberKeyPosition=new ArrayList<NumberKeyPosition>();
		String expression="\"\\d*\":";
		Pattern p = Pattern.compile(expression);
		Matcher m = p.matcher(jsonString);
		StringBuffer sb = new StringBuffer();
		int prevIndex=0;
		while (m.find()) {
			NumberKeyPosition numberKeyPosition=new NumberKeyPosition();
			String matchString=m.group();
			int currentIndex=Integer.parseInt(matchString.trim().replace("\"", "").replace(":", ""));
			numberKeyPosition.setStartPos(m.start());
			numberKeyPosition.setEndPos(m.end());
			//System.out.println("Start Pos:"+m.start());
			//System.out.println("End Pos:"+m.end());
			if(currentIndex==1){
				numberKeyPosition.setFirstOne(true);
				if(prevIndex==1){
					if(lsNumberKeyPosition.size()>0){
					   lsNumberKeyPosition.get(lsNumberKeyPosition.size()-1).setLastOne(true);
					}
				}else{
					if(prevIndex>1){
						lsNumberKeyPosition.get(lsNumberKeyPosition.size()-1).setLastOne(true);
					}
				}
				
			}else{
					numberKeyPosition.setFirstOne(false);
					numberKeyPosition.setLastOne(false);
			}
			prevIndex=currentIndex;
			lsNumberKeyPosition.add(numberKeyPosition);
		}
		if(lsNumberKeyPosition!=null&&lsNumberKeyPosition.size()>0){
		  lsNumberKeyPosition.get(lsNumberKeyPosition.size()-1).setLastOne(true);
		}
		return lsNumberKeyPosition;
	}
	/**
	 * 
	 * @param endOfLastPositionString
	 * @return
	 * @Test data: {   "background": "#f83a22",   "foreground": "#1d1d1d"  } }, "event": {  
	 *  {   "background": "#f83a22",   "foreground": "#1d1d1d"  } }, "event": {
	 */
	public String addBracket4EndPostion(String endOfLastPositionString){
		StringBuffer sBuffer=new StringBuffer();
		int leftBracketCount=0;
		int leftBracketCountFirstIndex=endOfLastPositionString.indexOf('{');
		boolean isAddBracketSucc=false;
		boolean isRemovedLaterBrace=false;
		for(int i=0;i<endOfLastPositionString.length();i++){
			if(endOfLastPositionString.charAt(i)=='{'){
				leftBracketCount++;
			} else if(endOfLastPositionString.charAt(i)=='}'){
				leftBracketCount--;
			}
			sBuffer.append(endOfLastPositionString.charAt(i));
			if(leftBracketCount==0&&i>leftBracketCountFirstIndex&&!isAddBracketSucc){
				sBuffer.append(']');
				isAddBracketSucc=true;
				continue;
			}
			if(isAddBracketSucc&&!isRemovedLaterBrace&&endOfLastPositionString.charAt(i)=='}'){
				int lenStringBuffer=sBuffer.length();
				sBuffer=new StringBuffer(sBuffer.substring(0, lenStringBuffer-1));
				isRemovedLaterBrace=true;
			}
			
		}
		return sBuffer.toString();
	}
	
	private String trimRightBrace(String tmpString) {
		String trimRightBraceString = "";
		if (tmpString != null) {
			tmpString=tmpString.trim();
			int len = tmpString.length();
			if (len > 1 && tmpString.endsWith("{")) {
				trimRightBraceString = tmpString.substring(0, len - 2);
			}
		}
		return trimRightBraceString;
	}
	/**
	 * getRemovedNumberKeyJSONString
	 * @return
	 */
	public String getRemovedNumberKeyJSONString(){
		//String removedNumberKeyJSONString=null;
		List<NumberKeyPosition> lsNumberKeyPosition=this.getNumberKeyPositions();
		StringBuffer sbBuffer=new StringBuffer();
		if(lsNumberKeyPosition!=null&&lsNumberKeyPosition.size()>0){
			for(int i=0;i<lsNumberKeyPosition.size();i++){
				NumberKeyPosition currentnumberKeyPosition=lsNumberKeyPosition.get(i);
				if(i==0){
					    String tmpString=jsonString.substring(0, currentnumberKeyPosition.getStartPos()).trim();
					    sbBuffer.append(trimRightBrace(tmpString));
					    sbBuffer.append("[");
				}else{
					NumberKeyPosition preNumberKeyPosition=lsNumberKeyPosition.get(i-1);
					if(currentnumberKeyPosition.isFirstOne()){
						sbBuffer.append("[");
					}else{
						if(currentnumberKeyPosition.isLastOne()){
							sbBuffer.append(jsonString.substring(preNumberKeyPosition.getEndPos(), currentnumberKeyPosition.getStartPos()));
							if(i<lsNumberKeyPosition.size()-1){
								NumberKeyPosition nextNumberKeyPosition=lsNumberKeyPosition.get(i+1);
								String endOfLastPositionString=jsonString.substring(currentnumberKeyPosition.getEndPos(),nextNumberKeyPosition.getStartPos()).trim();
								sbBuffer.append(addBracket4EndPostion(trimRightBrace(endOfLastPositionString)));
							}else{
								String endOfLastPositionString=jsonString.substring(currentnumberKeyPosition.getEndPos(),jsonString.length());
								sbBuffer.append(addBracket4EndPostion(endOfLastPositionString));
							}
						}else{
							sbBuffer.append(jsonString.substring(preNumberKeyPosition.getEndPos(), currentnumberKeyPosition.getStartPos()));
						}
					}
				}	
			}
		}
		return sbBuffer.toString();
	}
	public static void main(String[] args) {
		CovertNumberKeyAsArrayUtil covertNumberKeyAsArrayUtil=new CovertNumberKeyAsArrayUtil();
		covertNumberKeyAsArrayUtil.setJsonString(covertNumberKeyAsArrayUtil.readFileAsString("jsonColorNumber.json"));
		String removedNumberKeyJSONString=covertNumberKeyAsArrayUtil.getRemovedNumberKeyJSONString();
		System.out.println(removedNumberKeyJSONString);
	}

}








分享到:
评论

相关推荐

    Pro RESTful APIs Design Build and Integrate with REST JSON XML and JAX-RS 无水印pdf

    Pro RESTful APIs Design Build and Integrate with REST JSON XML and JAX-RS 英文无水印pdf pdf所有页面使用FoxitReader和PDF-XChangeViewer测试都可以打开 本资源转载自网络,如有侵权,请联系上传者或csdn...

    Pro.RESTful.APIs.Design.Build.and.Integrate.with.REST.JSON.XML.and.JAX-RS.pdf

    Discover the RESTful technologies, including REST, JSON, XML, JAX-RS web services, SOAP and more, for building today's microservices, big data applications, and web service applications. This book is ...

    Java XML and JSON

    XML and (the more popular) JSON let you organize data in textual formats. This book introduces you to these technologies along with Java APIs for integrating them into your Java code. This book ...

    Java XML and JSON(Apress,2016)

    This is your one-stop guide to mastering the XML metalanguage and JSON data format along with significant Java APIs for parsing and creating XML/JSON documents (and more). The first six chapters focus...

    Java XML and JSON: Document Processing for Java SE, 2nd Edition

    Java XML and JSON: Document Processing for Java SE By 作者: Jeff Friesen ISBN-10 书号: 1484243293 ISBN-13 书号: 9781484243299 Edition 版本: 2nd ed. 出版日期: 2019-01-11 pages 页数: (548 ) $44.99 Use ...

    Creating.Maintainable.APIs.A.Practical.Case-Study.Approach

    Build straightforward and maintainable APIs to create services that are usable and maintainable. Although this book focuses on distributed services, it also emphasizes how the core principles apply ...

    Creating Maintainable APIs(Apress,2016)

    Build straightforward and maintainable APIs to create services that are usable and maintainable. Although this book focuses on distributed services, it also emphasizes how the core principles apply ...

    Extjs Tree + JSON + Struts2 示例源代码

    在我的随笔Extjs Tree + JSON + Struts2中我介绍了如何异步加载一个Extjs的树,但是很多网友留言说不能成功操作。现在我自己做了一个所有源代码的包,供大家下载。 有几点事项请大家注意 1、blogjava的文件上载要求...

    meteor-api-handling:在meteor中处理不同的apis(xml,json)

    流星API处理在meteor 中处理不同的apis(xml,json) 并弄清楚它是如何工作的

    Ajax-vue-apis.zip

    Ajax-vue-apis.zip,腋窝,ajax代表异步javascript和xml。它是多种web技术的集合,包括html、css、json、xml和javascript。它用于创建动态网页,其中网页的小部分在不重新加载网页的情况下更改。

    c3p0-0.9.1.2等等

    jaxen-1.1-beta-7 jdbc2_0-stdext jotm json-lib-2.3-jdk15-javadoc jta jxl log4j-1.2.11 log4j-1.2.14 portlet-api spring-agent spring-aop spring-beans spring-context spring-core spring-dao spring-...

    java开发常用jar包

    Hibernate使用dom4j解析XML配置文件和XML映射元文件。必需的。 ehcache-1.2.jar Hibernate可以使用不同cache缓存工具作为二级缓存。EHCache是缺省的cache缓存工具。如果没有其它的可选缓存工具,则为必需的。 ...

    web开发常用jar

    Hibernate使用dom4j解析XML配置文件和XML映射元文件。必需的。 ehcache-1.2.jar Hibernate可以使用不同cache缓存工具作为二级缓存。EHCache是缺省的cache缓存工具。如果没有其它的可选缓存工具,则为必需的。 ...

    dsc-apis-section-intro-online-ds-pt-031119

    在本部分中,您将获得一些动手操作的经验,这些经验是检索和使用由各种不同的API提供的数据的经验。 API简介 我们从提供有关各种API的概念性介绍以及企业创建它们的一些原因开始,开始本节。 客户端服务器模型 然后...

    dsc-apis-section-intro-online-ds-pt-071519

    在本部分中,您将获得一些动手操作的经验,这些经验是检索和使用由各种不同的API提供的数据的经验。 API简介 我们从提供有关各种API的概念性介绍以及企业创建它们的一些原因开始,开始本节。 客户端服务器模型 然后...

    Spring主流jar包大全

    activiti-json-converter-5.21.0.jar activiti-modeler-5.21.0.jar activiti-process-validation-5.21.0.jar activiti-spring-5.21.0.jar analyzer-2012_u6.jar aopalliance-1.0.jar apache-ant-zip-2.3.jar asm-4.2...

    dsc-apis-section-intro-data-science

    在本部分中,您将获得一些动手操作的经验,这些经验是检索和使用由各种不同的API提供的数据的经验。 API简介 我们从提供有关各种API的概念性介绍以及企业创建它们的一些原因开始,开始本节。 客户端服务器模型 然后...

    dsc-apis-section-intro-dc-ds-100719

    在本部分中,您将获得一些动手操作的经验,这些经验是检索和使用由各种不同的API提供的数据的经验。 API简介 我们从提供有关各种API的概念性介绍以及企业创建它们的一些原因开始,开始本节。 客户端服务器模型 然后...

    google api php client

    [Build Status](https://travis-ci.org/google/google-api-php-client.svg?branch=master)](https://travis-ci.org/google/google-api-php-client) # Google APIs Client Library for PHP # The Google API Client...

    PHP.Web.Services.APIs.for.the.Modern.Web.2nd.Edition

    Whether you’re sharing data between two internal systems or building an API so users can access their data, this practical book provides everything you need to build web service APIs with ...

Global site tag (gtag.js) - Google Analytics