最近项目中用到json这个数据结构,由于jdk1.6并没有提供默认解析json的api,项目中选用了apache的json工具类来做解析,目前常用的json解析工具还有google提供的gson和阿里的fastjson。
网上瞅了半天,想了下,json解析无非是对字符串做遍历,忍不住自己尝试解析下,通过递归实现一次字符串的完整遍历来完成json字符串与Map的转换。
首先列出json中常用的几个特殊字符:' " : [ ] { }。
- ‘和"这两个字符之前的部分是json的key或是value,对于这种字符,只需要取出之间的字符串即可
- :这个字符之前的json的key,后面的是json的value
- []这两个字符之间的部分可以看做是java中的list,他们一般是json的value,因为json是按{key:value}这个格式来存储的,所以不会选择[]来作为json的key
- {}跟[]差不多,可以看做是java的map。
java解析json过程中,需要考虑{}和[]之间的嵌套,同时当前被解析节点的是在map还是list中,如:
{'_key1':'_v1','_key2':'_v2'} //其中_key1、_v1、_key2、_v2都是在map中。
而
{'_list':['a','b']} //a、b都是位于list中,而['a','b']则在map中。
实现方法:顺序解析json字符串,当遇到{}或[]时递归调用当前方法,递归完成之后将字符串搜索的位置移动到]或}处继续遍历。
代码如下:
package com.json;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
@SuppressWarnings({"unchecked","rawtypes"})
public class JSON2Map{
private static final Logger log = Logger.getLogger("parse");
public static Map getMap(String json){
return parse(json);
}
public static Map parse(String json){
if(json == null){
log.error("json is null.");
}
HashMap jsonObj = new HashMap();
json = json.trim();
if(json.startsWith("{")){
parse(json.substring(1), jsonObj, true);
}
return jsonObj;
}
public static int parse(String json, Object obj, boolean isMap){
/*
json: 待解析的json字符串
obj :当前json串的父节点
isMap: 当前解析的json串是位于map中还是list中。
*/
HashMap jsonObject = null;
ArrayList jsonArray = null;
int word_s_position = 0;
int word_e_position = 0;
String word = "";
//'或"分隔符是一个单词开头还是结尾
boolean isStart = true;
//当前值是json的key还是value
boolean isKey = true;
if(isMap){
jsonObject = (HashMap) obj;
} else {
jsonArray = (ArrayList) obj;
}
int len = json.length();
char current_char = ' ';
for(int x=0; x<len; x++){
current_char = json.charAt(x);
switch(current_char){
case '\'':
case '\"':
if(isStart) {
word_s_position = x+1;
isStart = false;
} else {
word_e_position = x;
if(isMap){
//父节点为map
if(isKey){
//当前为key
word = json.substring(word_s_position, word_e_position);
log.debug("current is key, the value is: >>>> "+word);
jsonObject.put(word, null);
} else {
log.debug("current is value, the value is: >>>> "+json.substring(word_s_position, word_e_position));
jsonObject.put(word, json.substring(word_s_position, word_e_position));
isKey = true;
}
} else {
jsonArray.add(json.substring(word_s_position, word_e_position));
}
isStart = true;
}
break;
case '{' :
HashMap _jsonObj = new HashMap();
if(isMap){
jsonObject.put(word, _jsonObj);
} else {
jsonArray.add(_jsonObj);
}
int pass_obj_char = parse(json.substring(x+1), _jsonObj, true);
x += pass_obj_char;
log.debug("current parsing json string is : "+ json);
log.debug("parsed json string is: " + json.substring(0, x));
log.debug("remain to parsing json string is:"+json.substring(x+1));
break;
case '[' :
ArrayList _jsonArray = new ArrayList();
if(isMap){
jsonObject.put(word, _jsonArray);
} else {
jsonArray.add(_jsonArray);
}
int pass_array_char = parse(json.substring(x+1), _jsonArray, false);
x += pass_array_char;
log.debug("current parsing json string is : "+ json);
log.debug("parsed json string is: " + json.substring(0, x));
log.debug("remain to parsing json string is:"+json.substring(x+1));
break;
case '}' :
//结束当前map
return x+1;
case ']' :
//结束当前list
return x+1;
case ',' :
if(isMap){
isKey = true;
} else {
isKey = false;
}
break;
case ':' :
isKey = false;
break;
}
}
return json.length();
}
}
调用方法
String json = "{'abc':'ac','acb':'ae','arr1':[{'subArr1':{'abc':'ac','acb':'ae','arr1':[{'subArr1':'subArr2'},{'subArr2':'subArr3'}]}},{'subArr2':'subArr3'}],'key2':'value2','et':{'ab':'er','a':'re'},'key1':'value1'}";
Map map = JSON2Map.getMap(json);
log.debug(map);