1、遞歸一
有的時候我們需要解析未知的json。或者說是動態的json。那么我們並不知道key具體是多少,或者說key不是固定的。這時候就需要解析動態key的方法。
這個方法是我在實現解析前台傳入的json時所需要的。因為每個界面的前台傳的是json是不固定的。如果真對每一個頁面所傳的數據都單獨進行一次解析,那么太麻煩了。所以需要一個通用的解析方式。將其解析到map中。那么只需要調用該方法,就能獲取到前台所傳json對於的map。
在網上搜了一會,找不到我想要的方法,即不和我心意,代碼又不給全。所以自己測試了一個簡單的代碼。我是使用遞歸實現的,代碼簡單。就不一一講解了,如果還有不清楚的,請留言。
1 import java.util.HashMap; 2 import java.util.Iterator; 3 import java.util.Map; 4 import java.util.Set; 5 6 import net.sf.json.JSONObject; 7 8 public class JsonTest { 9 public static void main(String[] args) { 10 //測試字符串 11 String test = "{a:1,b:2,c:3,d:{q:4,w:5,e:6,y:{o:7,p:8}}}"; 12 Map res = new HashMap(); 13 //遞歸遍歷解析方法 14 iteraJson(test,res); 15 //解析得到最終map后,遍歷該map輸出值 16 Set keySet = res.keySet(); 17 Iterator iterator = keySet.iterator(); 18 while(iterator.hasNext()){ 19 String key = iterator.next().toString(); 20 Object val = res.get(key); 21 System.out.println(key+":"+val.toString()); 22 } 23 } 24 //遞歸遍歷解析方法 25 public static boolean iteraJson(String str,Map res){ 26 //因為json串中不一定有逗號,但是一定有:號,所以這里判斷沒有則已經value了 27 if(str.toString().indexOf(":") == -1){ 28 return true; 29 } 30 JSONObject fromObject = JSONObject.fromObject(str); 31 Iterator keys = fromObject.keys(); 32 while(keys.hasNext()){ 33 String key = keys.next().toString(); 34 Object value = fromObject.get(key); 35 if(iteraJson(value.toString(),res)){ 36 res.put(key, value); 37 } 38 } 39 return false; 40 } 41 }
效果如下:
2、遞歸二
上面的遞歸方式只支持沒有包含數組格式的json字符串。例如:
String test = "{a:1,b:[1,2,3],c:3,d:{q:4,w:5,e:6,y:{o:7,p:8}},arry:[{name1:'joker',age:30},{name2:'dd',age:20},{name3:'bb',age:10}]}";
b:[1,2,3] 這個數組是正規數組,不是json數組,不需要解析。
arry:[{name1:’joker’,age:30},{name2:’dd’,age:20},{name3:’bb’,age:10}]。這個是json數組,需要繼續解析。
要實現這兩個格式的兼容。下面的代碼能夠實現:
1 public static boolean iteraJsonOrArray(String source,Map map){ 2 if(source.indexOf(":") == -1){ 3 return true; 4 } 5 JSONObject fromObject = JSONObject.fromObject(source); 6 Iterator keys = fromObject.keys(); 7 while(keys.hasNext()){ 8 String key = keys.next().toString(); 9 Object value = fromObject.get(key); 10 String val = value.toString(); 11 if(val.indexOf("[{") == -1){ 12 //說明不存在數組json即格式為:"[{" 開頭的數據。可以允許是[10,11,12]的非json數組 13 if(val.indexOf(":") == -1){ 14 map.put(key, val); 15 }else{ 16 iteraJson(val,map); 17 } 18 }else if(val.indexOf("[{") != -1){ 19 //說明存在數組json即格式為:[{開頭的json數組 20 if(val.indexOf("[{") == 0){ 21 //說明當前value就是一個json數組 22 //去除[括號 23 String jsons = val.substring(1, val.lastIndexOf("]"));//得到數據格式為:{...},{...},{...} 24 //把上面得到jsons分割成數組 25 //因為數據格式為{name:joker,age:20},{...},{...},所以不能用逗號分割。否則會變"{name:joker" "age:20}" 26 //使用正則表達式把},{替換成}|{ 27 jsons = jsons.replaceAll("\\}\\s?,\\s?\\{", "}|{"); 28 String[] split = jsons.split("\\|"); 29 for(int i = 0; i < split.length;i++){ 30 iteraJsonOrArray(split[i],map);//符合當前遞歸條件 31 } 32 33 }else{ 34 //說明value可能是一個json,這個json中任然包含數組。例如:{inner:[{a:1,b:2,c:3}]} 35 iteraJsonOrArray(val,map);//符合當前遞歸條件 36 } 37 } 38 39 } 40 41 return false; 42 }
把 iteraJsonOrArray 方法寫到遞歸一中的代碼里。因為這個方法里調用了遞歸一中的iteraJson來解析沒包含任何數組類型的json串。
執行代碼
1 String test = "{a:1,b:[1,2,3],c:3,d:{q:4,w:5,e:6,y:{o:7,p:8}},arry:[{name1:'joker',age:30},{name2:'dd',age:20},{name3:'bb',age:10}]}"; 2 Map res = new HashMap(); 3 iteraJsonOrArray(test,res); 4 Set keySet = res.keySet(); 5 Iterator iterator = keySet.iterator(); 6 while(iterator.hasNext()){ 7 String key = iterator.next().toString(); 8 Object val = res.get(key); 9 System.out.println(key+":"+val.toString()); 10 }
效果如下:
注意:上圖中 的name我分為name1,name2,name3。上圖只有一個age。因為key重名了,所以放入map中自然會被覆蓋掉。如果三個name一樣,最后只能得到一個name一個age.
**
3、遞歸三
**
遞歸二的方式可以實現大部分json格式。但是遇到key相同的json就不好保存數據。
比如:{arry:[{name:joker,age:15},{name:jake,age:20},{name:mari,age:25}]};這種格式用遞歸二的話,放入map中,最后只得到name:mari 和 age:25。
所以我們需要把所有的值都保存起來,那么就不是放入map中,而是list中了。
如下圖,在遞歸二中創建臨時tempmap和list。然后把list添加到最終map中。
輸出結果為:
這樣就可以接受前台傳到后台的json數據。這個json數據可以包含表單的值和表格的值一起。
---------------------
轉自:https://blog.csdn.net/Esc_Tab_End/article/details/80210659