話說好久沒更新這個博客了
都快忘記還有博客這件事了....
因為之前在造一個簡單的HTTP框架的輪子,裡面用了JSON...當時隨便拉了個FastJSON的庫就用了,然而...嗯,毫無疑問,輪子還是要自己造才好玩,雖然不會在生產環境用,但是寫和不寫多少還是有些差距的
於是今天就造了這個簡單的JSON庫輪子,實現了FastJSON裡最常用的toJSON和fromJSON功能,支持Map List Array BeanObject 的JSON文本轉換,JSON文本解析的話只實現了到Map和List的解析...BeanObject懶得寫了,等以後輪子的坑造完了完善後再一起丟到Github玩好了
總之簡單的放一下這個毫無效率的MyJSON代碼,為了實現簡單各種遞歸應該不復雜,至於兼容性...不知道,沒測試多少測試用例,如果有BUG歡迎評論反饋(循環引用會導致生成json文本死循環,對此並不打算修復...嗯,說到底JSON裡我怎麼才能表示的出循環引用啊
對了,寫這個的時候完全沒有參考JSON規范....全靠自己對JSON的理解強行撸出來的,如果有不符合規范的地方歡迎指正QwQ
從對象生成JSON(所有的包引用就不貼了)
1 /** 2 * 根據對象封裝到JSON文本,支持Map,List和Bean對象,如果鍵是一個對象,那麼需要自行重寫toString 3 * @param object 4 * @return 5 */ 6 public static String toJSON(Object object){ 7 StringBuffer jsonString = new StringBuffer(); 8 if (object instanceof Map){ 9 getMapObjectText(jsonString,object); 10 }else if(object instanceof List || object.getClass().isArray()){ 11 getListObjectText(jsonString,object); 12 }else{ 13 getBeanObjectText(jsonString,object); 14 } 15 return jsonString.toString(); 16 } 17 //從Object中解析並生成JSON字符串,如果無法作為Java Bean解析,則直接toString輸出文本 18 private static void getBeanObjectText(StringBuffer json,Object object) { 19 int i = 0; 20 try{ 21 Class c = object.getClass(); 22 Field[] fields = c.getDeclaredFields(); 23 for(Field field : fields){ 24 PropertyDescriptor pd = new PropertyDescriptor(field.getName(), c); 25 Method getMethod = pd.getReadMethod(); 26 Object value = getMethod.invoke(object); 27 if (i++ == 0) 28 json.append("{"); 29 else 30 json.append(","); 31 json.append("\"").append(field.getName()).append("\":"); 32 getValueText(json, value); 33 } 34 }catch(Exception e){} 35 if (i != 0) 36 json.append("}"); 37 else 38 json.append("\"").append(object.toString()).append("\""); 39 } 40 //從Map中解析並生產JSON字符串 41 private static void getMapObjectText(StringBuffer json,Object object){ 42 Map<Object,Object> map = (Map)object; 43 json.append("{"); 44 int i = 0; 45 for(Entry entry : map.entrySet()){ 46 if (entry.getKey() != null){ 47 if (i++ != 0){ 48 json.append(","); 49 } 50 json.append("\"").append(entry.getKey().toString()).append("\":"); 51 getValueText(json, entry.getValue()); 52 } 53 } 54 json.append("}"); 55 } 56 //從List或者Arrays中解析並生成JSON字符串 57 private static void getListObjectText(StringBuffer json,Object object){ 58 json.append("["); 59 List list = null; 60 if(object.getClass().isArray()){ 61 list = Arrays.asList((Object[])object); 62 } 63 if (list == null) 64 list = (List)object; 65 int i = 0; 66 for(Object value : list){ 67 if (i++ != 0) 68 json.append(","); 69 getValueText(json, value); 70 } 71 json.append("]"); 72 } 73 //獲取value的值並寫入json字符串中 74 private static void getValueText(StringBuffer json,Object value){ 75 if (value == null){ 76 json.append("null"); 77 return; 78 } 79 if (value instanceof String)//基本數據類型處理 80 json.append("\"").append(encoderJsonText(value.toString())).append("\""); 81 else if(value instanceof Integer) 82 json.append(((Integer) value).intValue()); 83 else if(value instanceof Boolean) 84 json.append(((Boolean) value).booleanValue()); 85 else if(value instanceof Character) 86 json.append("\"").append(value.toString()).append("\""); 87 else if(value instanceof Long) 88 json.append(((Long) value).longValue()); 89 else if(value instanceof Double) 90 json.append(((Double) value).doubleValue()); 91 else if(value instanceof Float) 92 json.append(((Float) value).floatValue()); 93 else if(value instanceof Map)//Map List Arrays Bean遞歸處理 94 getMapObjectText(json,value); 95 else if(value instanceof List || value.getClass().isArray()) 96 getListObjectText(json,value); 97 else 98 getBeanObjectText(json, value); 99 } 100 //對JSON中的文字進行編碼轉換,主要是"換行等符號的轉義 101 private static String encoderJsonText(String s){ 102 s = s.replace("\"", "\\\""); 103 s = s.replace("\\", "\\\\"); 104 s = s.replace("\n", "\\\n"); 105 return s; 106 }
使用方法(Bean對象請自行腦補)
1 TestBean bean = new TestBean(); 2 bean.setBean1("Stri\"ngTe[]}xt"); 3 bean.setBeanBool(true); 4 bean.setBeanFloat((float)3.14); 5 bean.setBeanInt(233); 6 Map<String,Object> map = new HashMap<>(); 7 map.put("test", "a"); 8 map.put("test2", 0); 9 map.put("test3", new Object()); 10 Map<String,Object> map2 = new HashMap<>(); 11 map2.put("map2", "qwq"); 12 Object[] array = new Object[]{"1","2",map2}; 13 bean.setBeanMap(map); 14 bean.setBeanList(Arrays.asList(array)); 15 System.out.println(MyJSON.toJSON(bean));
接下來上JSON解析代碼,思路和上面一樣,全靠遞歸簡化
1 private final static char[] BLANKLIST = new char[]{' ','\t','\r','\n'};//空白字符 2 private final static char[] LISTENDS = new char[]{',',']'};//LIST結束字符 3 private final static char[] MAPENDS = new char[]{',','}'};//MAP結束字符 4 private final static char[] COLONCHAR = new char[]{':'};//冒號CHAR 5 private final static char[] QUOTESCHAR = new char[]{'"'};//引號CHAR 6 7 /** 8 * 解析JSON並返回解析結果,如果是鍵值對則封裝成Map,如果是有序集合則封裝成List 9 * @param json 10 * @return 11 */ 12 public static Object fromJSON(String json){ 13 json = json.trim(); 14 if (json.startsWith("{")) 15 return getMapObjectFromJson(json, new int[]{1}); 16 else if (json.startsWith("[")) 17 return getListObjectFromJson(json, new int[]{1}); 18 else 19 throw new IllegalArgumentException("開頭不是{或者["); 20 } 21 //根據JSON文本封裝成Map,pos為當前處理位置 22 private static Map getMapObjectFromJson(String json,int[] pos){ 23 Map<String,Object> resultMap = new HashMap<>(); 24 while(pos[0] < json.length()){ 25 //跳到第一個" 26 jumpCharByChars(json, pos, QUOTESCHAR); 27 //取到下一個"為止是key 28 String key = getCharsByEnds(json, pos, QUOTESCHAR); 29 pos[0]++;//跳過"符號 30 //跳到中間分割字符: 31 jumpCharByChars(json, pos, COLONCHAR); 32 //跳到下一個非空值為止 33 jumpCharByChars(json,pos,null); 34 pos[0]--;//調回非空值第一個數據 35 char c = json.charAt(pos[0]); 36 if (c == '{'){//是一個嵌套Map 37 pos[0]++;//跳過{符號 38 resultMap.put(key, getMapObjectFromJson(json, pos)); 39 }else if(c == '['){//是一個嵌套List 40 pos[0]++;//跳過[符號 41 resultMap.put(key, getListObjectFromJson(json, pos)); 42 }else if(c == '"'){//文本值處理 43 pos[0]++; 44 String value = getCharsByEnds(json, pos, QUOTESCHAR); 45 pos[0]++; 46 resultMap.put(key, decoderJsonText(value)); 47 }else{//其他格式處理 48 String value = getCharsByEnds(json, pos, MAPENDS); 49 resultMap.put(key, getTextValue(value)); 50 } 51 if (isEnds(json,pos))//是否結束 52 return resultMap; 53 } 54 throw new IllegalArgumentException("異常的結尾,請檢查JSON字符串是否完整"); 55 } 56 //根據JSON中的文本值獲取對應實例(主要是int bool null三種特殊值) 57 private static Object getTextValue(String s){ 58 s = s.trim(); 59 if ("true".equals(s)) 60 return true; 61 if ("false".equals(s)) 62 return false; 63 if ("null".equals(s)) 64 return null; 65 if (s.indexOf(".")==-1){ 66 try{ 67 return Integer.parseInt(s); 68 }catch(NumberFormatException e){ 69 return Long.parseLong(s); 70 } 71 }else{ 72 try{ 73 return Float.parseFloat(s); 74 }catch(NumberFormatException e){ 75 return Double.parseDouble(s); 76 } 77 } 78 } 79 //根據JSON文本封裝成List,pos為當前處理位置 80 private static List getListObjectFromJson(String json,int[] pos){ 81 List<Object> resultList = new ArrayList<>(); 82 while(pos[0] < json.length()){ 83 jumpCharByChars(json, pos, null); 84 pos[0]--; 85 char c = json.charAt(pos[0]); 86 if (c == '{'){ 87 pos[0]++; 88 resultList.add(getMapObjectFromJson(json, pos)); 89 }else if (c == '['){ 90 pos[0]++; 91 resultList.add(getListObjectFromJson(json, pos)); 92 }else if (c == '"'){ 93 pos[0]++; 94 String value = getCharsByEnds(json, pos, QUOTESCHAR); 95 pos[0]++; 96 resultList.add(decoderJsonText(value)); 97 }else{ 98 String value = getCharsByEnds(json, pos, LISTENDS); 99 resultList.add(getTextValue(value)); 100 } 101 if (isEnds(json,pos)) 102 return resultList; 103 } 104 throw new IllegalArgumentException("異常的結尾,請檢查JSON字符串是否完整"); 105 } 106 //判斷是否結束 107 private static boolean isEnds(String json,int[] pos){ 108 int i = pos[0]; 109 while(i < json.length()){ 110 char c = json.charAt(i++); 111 if (!isBlank(c)){ 112 if (c == '}' || c == ']'){ 113 pos[0] = i; 114 return true; 115 }else if (c == ','){ 116 pos[0] = i; 117 return false; 118 }else 119 throw new IllegalArgumentException("未知的字符[" + c + "],在"+i+"位置"); 120 } 121 } 122 throw new IllegalArgumentException("異常的結尾,請檢查JSON字符串是否完整"); 123 } 124 //根據chars跳過一定數量的位置,如果遇到非空且不在chars中的字符則拋出異常 125 private static void jumpCharByChars(String json,int[] pos,char[] chars){ 126 while(pos[0] < json.length()){ 127 char c = json.charAt(pos[0]); 128 if (!isBlank(c)){ 129 if (charInChars(c,chars)) 130 break; 131 throw new IllegalArgumentException("未知的字符[" + c + "],在"+pos[0]+"位置"); 132 } 133 pos[0]++; 134 } 135 pos[0]++; 136 if (pos[0] > json.length()) 137 throw new IllegalArgumentException("異常的結尾,請檢查JSON字符串是否完整"); 138 } 139 //根據ends來獲取ends前的所有內容文本,轉義字符完整輸出不作處理 140 private static String getCharsByEnds(String json,int[] pos,char[] ends){ 141 CharArrayWriter out = new CharArrayWriter(1); 142 while(pos[0] < json.length()){ 143 char c = json.charAt(pos[0]); 144 if (c == '\\'){ 145 out.write(c); 146 out.write(json.charAt(++pos[0])); 147 }else if(charInChars(c,ends)){ 148 break; 149 }else{ 150 out.write(c); 151 } 152 pos[0]++; 153 } 154 if (pos[0]+1 > json.length()) 155 throw new IllegalArgumentException("異常的結尾,請檢查JSON字符串是否完整"); 156 String result = null; 157 result = new String(out.toCharArray()); 158 out.close(); 159 return result; 160 } 161 //檢測字符是不是在字符數組中 162 private static boolean charInChars(char c,char[] chars){ 163 if (chars == null) 164 return true; 165 for(char cc : chars) 166 if (cc == c) 167 return true; 168 return false; 169 } 170 //檢測字符是不是空白 171 private static boolean isBlank(char s){ 172 for(char c : BLANKLIST) 173 if (s == c) 174 return true; 175 return false; 176 } 177 //解碼JSON文本,主要是對轉義字符的解釋 178 private static String decoderJsonText(String s){ 179 s = s.replace("\\\"", "\""); 180 s = s.replace("\\\\", "\\"); 181 s = s.replace("\\\n", "\n"); 182 return s; 183 }
使用方法
1 public void test(){ 2 Map m = (Map)MyJSON.fromJSON("{\"test\":[{\"test\":2},{\"test2\":[1,2,3]}]}"); 3 System.out.print(m); 4 }