突發奇想要造一個輪子,處理JSON字符串
特點:
1. 能夠正確處理括號嵌套,但是可能會受到json中嵌套的特殊帶有干擾性的單括號影響,有時間可結合第2點完善。
2. 能夠正確處理帶有轉義引號的字符串。
3. 對json的鍵值對定位處理類似於新版MySQL中的處理方式“attr1.$2.subattr2”,這裏$2代表找這個數組第二個
4. JSON的定義:
完整代碼如下:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Json {
// json的六種value
public static final int TYPE_OBJ = 1;
public static final int TYPE_ARR = 2;
public static final int TYPE_STR = 3;
public static final int TYPE_NUM = 4;
public static final int TYPE_BOL = 5;
public static final int TYPE_NUL = 6;
// json的六種value的匹配正則
public static final String RE_OBJ = "\\s*(\\{(.*)\\})\\s*"; // 匹配Object : {},但是嵌套會出錯
public static final String RE_ARR = "\\s*(\\[(.*?)\\])\\s*"; // 匹配數組[],但是嵌套會出錯
public static final String RE_STR = "\\s*((((?<!\\\\)\")(.*?)((?<!\\\\)\")))\\s*";// 匹配字符串,且能正確處理轉義引號
public static final String RE_NUM = "\\s*((-?(\\d+\\.)?\\d+))\\s*"; // 匹配任意數字
public static final String RE_BOL = "\\s*(((true)|(True)|(TRUE)|T|(false)|(False)|(FALSE)|F))\\s*"; // 匹配Boolean類型
public static final String RE_NUL = "\\s*(((NULL)|(Null)|(null)|(nul)|(NUL)|(Nul)|(NaN)))\\s*"; // 匹配空值
public int type;
public Map<String, Json> values;
public List<Json> array;
public String self;
public Json() {
this("{}");
}
public Json(String val) {
super();
self = val;
if (test(RE_OBJ, val)) {
this.type = TYPE_OBJ;
values = new HashMap<String, Json>();
String fk, fv;
int rc = match(val, "{", "}");
String content = val.substring(1, rc);
while (content.length() > 0) {
fk = firstVal(content);
if (fk == null || fk.equals("{}"))
break;
// Log.log(content,fk);
content = content.substring(fk.length() + 1);
fv = firstVal(content);
boolean next = fv.length() < content.length();
values.put(sv(fk), new Json(fv));
if (next) {
content = content.substring(fv.length() + 1);
} else {
break;
}
}
} else if (test(RE_ARR, val)) {
this.type = TYPE_ARR;
this.array = new ArrayList<Json>();
int index = match(val, "[", "]");
String str = val.substring(1, index);
String fv;
while (str.length() > 0) {
fv = firstVal(str);
boolean next = fv.length() < str.length();
if (next) {
str = str.substring(fv.length() + 1);
} else {
str = str.substring(fv.length());
}
array.add(new Json(fv.trim()));
}
} else if (test(RE_STR, val)) {
this.type = TYPE_STR;
} else if (test(RE_NUM, val)) {
this.type = TYPE_NUM;
} else if (test(RE_BOL, val)) {
this.type = TYPE_BOL;
} else if (test(RE_NUL, val)) {
this.type = TYPE_NUL;
} else {
this.type = TYPE_STR;
this.self = ss(val);
// this = new Json(ss(val));
// System.out.println("未能識別的片段:" + val);
}
}
// 測試類型
protected static boolean test(String REG, String str) {
REG = "^" + REG + "$";
boolean matches = Pattern.matches(REG, str);
// System.out.println(matches);
return matches;
}
// 獲取正則匹配到的某個單元
protected static String _get(String REG, String str, int which) {
Matcher matcher = Pattern.compile(REG).matcher(str);
String res = null;
if (which < 1) { // 用於測試觀察匹配結果
int groupCount = matcher.groupCount();
while (matcher.find()) {
System.out.println("=======");
for (int i = 0; i <= groupCount; i++) {
res = matcher.group(i);
System.out.println(res);
}
}
} else if (matcher.find()) {
res = matcher.group(which).trim();
// System.out.println(res);
}
return res;
}
// 計數以得到左邊括號的右邊對應
protected static int match(String str, String lt, String rt) {
int r = 0;
int i = 0;
for (; i < str.length() - 1; i++) {
if (str.substring(i, i + 1).equals(lt)) {
r++;
} else if (str.substring(i, i + 1).equals(rt)) {
r--;
}
if (r == 0) {
return i;
}
}
return i;
}
// 獲取最前面的一個單元的內部
protected static String firstVal(String str) {
String re = "null";
if (str.substring(0, 1).equals("{")) {
int index = match(str, "{", "}");
re = str.substring(0, index+1);
} else if (str.substring(0, 1).equals("[")) {
int index = match(str, "[", "]");
re = str.substring(0, index +1);
} else if(test(RE_STR+".*?",str)){
re = _get(RE_STR+".*?",str,2);
} else if(test(RE_NUM+".*?",str)){
re = _get(RE_NUM+".*?",str,2);
} else if(test(RE_BOL+".*?",str)){
re = _get(RE_BOL+".*?",str,2);
} else if(test(RE_NUL+".*?",str)){
re = _get(RE_NUL+".*?",str,2);
}else {
re = "null";
}
return re;
}
/**
* 返回序列化的JSON字符串
*/
@Override
public String toString() {
String str = "";
if (this.type == TYPE_OBJ) {
str += "{";
for (String k : values.keySet()) {
str += ss(k) + ":" + values.get(k) + ",";
}
if (str.length() > 1)
str = str.substring(0, str.length() - 1);
str += "}";
} else if (this.type == TYPE_ARR) {
str += "[";
for (int i = 0; i < array.size() - 1; i++) {
str += array.get(i) + ",";
}
if (array.size() > 0)
str += array.get(array.size() - 1);
str += "]";
} else {
str = self;
}
return str;
}
public static String sv(String ss) {
return ss.substring(1, ss.length()-1);
}
public static String ss(String sv) {
return "\""+sv+"\"";
}
public Json get(String mkey) {
int index = mkey.indexOf('.');
boolean inarray = mkey.startsWith("$");
try {
if(index>0) {
if(inarray) return this.array.get(Integer.parseInt(mkey.substring(1,index))).get(mkey.substring(index+1));
return this.values.get(mkey.substring(0,index)).get(mkey.substring(index+1));
}else {
if(inarray) return this.array.get(Integer.parseInt(mkey.substring(1,index)));
return this.values.get(mkey);
}
}catch(Exception e) {
return null;
}
}
/**
* 寫入爲String
* @param mkey
* @param value
* @return Json
* 例如: json.sets("name","張三")
*/
public Json sets(String mkey,String value) {
return this.set(mkey, ss(value));
}
/**
* 寫入非String的
* @param mkey
* @param value
* @return Json
* 例如: json.sets("age",110)
*/
public Json setn(String mkey,int value) {
return this.set(mkey, String.valueOf(value));
}
/**
* 不推薦使用
* @param mkey
* @param value
* @return
* 例如: json.sets("name","\"張三\"")
*/
public Json set(String mkey,String value) {
int index = mkey.indexOf('.');
boolean inarray = mkey.startsWith("$");
if(index>0) {
if(inarray) {
this.array.get(Integer.parseInt(mkey.substring(1,index))).set(mkey.substring(index+1),value);
}
else {
this.values.get(mkey.substring(0,index)).set(mkey.substring(index+1),value);
}
}else {
Json json = new Json(value);
if(inarray) {
int idx = Integer.parseInt(mkey.substring(1));
if(this.array==null) this.array = new ArrayList<Json>();
if(this.array.size()<idx+1) {
while (this.array.size()<idx+1) {
this.array.add(new Json(""));
}
}
// System.out.println(this);
this.array.set(idx,json);
}
else {
this.values.put(mkey,json);
}
}
return this;
}
/**
* 去除最外層的引號
* @return
*/
public String val() {
return sv(self);
}
// TODO 迭代器,用於對{} 和 []的遍歷
public void next(String key) {
}
// TODO 獲得 {}key的個數或者[]的個數
public void length(String mKey) {
}
// 測試
public static void main(String[] args) {
// String val = firstVal("NaNFlase19.80\"12\":\"43\"");
// System.out.println(val);
// String demo = "{\"name\":\"tim\",\"age\":24,\"rate\":0.9,\"active\":-0.83,\"major\":[{\"name\":\"數字\",\"score\":100},{\"name\":\"ds\",\"score\":{\"r1\":\"10\",\"r2\":100}}],\"test\":\"[\\\"name\\\",false,[],{\\\"1\\\":\\\"2\\\",\\\"3\\\":\\\"sanjin\\\"},[\\\"name\\\",false,[],{\\\"1\\\":\\\"2\\\",\\\"3\\\":\\\"sanjin\\\"},[]]]\",\"dic\":{}}";
// Json json = new Json(demo);
// System.out.println(json);
// System.out.println(json.get("major.$1.name"));
// System.out.println(json.set("major.$1.name","大佬"));
// System.out.println(json.set("test","[]"));
// Json json = new Json();
// json.set("cmd", "onlineList_OK");
// json.set("list", "[]");
// json.set("list.$0","123");
// System.out.print(json);
System.out.println(new Json("{\"clientId\":\"123456\",\"x\":11,\"y\":0,\"step\":0,\"cmd\":\"step\",\"ememyId\":\"13456\",\"isMyWhite\":false} ").get("ememyId"));
}
}
上述代碼運行效果如:
{"major":[{"name":"數字"},{"name":"ds"}],"test":"[\"name\",false,[],{\"1\":\"2\",\"3\":\"sanjin\"},[\"name\",false,[],{\"1\":\"2\",\"3\":\"sanjin\"},[]]]","rate":0.9,"name":"tim","active":-0.83,"age":24}
"ds"
{"major":[{"name":"數字"},{"name":"大佬"}],"test":"[\"name\",false,[],{\"1\":\"2\",\"3\":\"sanjin\"},[\"name\",false,[],{\"1\":\"2\",\"3\":\"sanjin\"},[]]]","rate":0.9,"name":"tim","active":-0.83,"age":24}
{"major":[{"name":"數字"},{"name":"大佬"}],"test":[],"rate":0.9,"name":"tim","active":-0.83,"age":24}
有待實現
- 遍歷
- 反序列化爲java對象