話說好久沒更新這個博客了
都快忘記還有博客這件事了....
因為之前在造一個簡單的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 }