[Java]簡單的JSON庫(重覆造輪子系列)

来源:http://www.cnblogs.com/pppploi8/archive/2016/10/30/6013972.html
-Advertisement-
Play Games

話說好久沒更新這個博客了 都快忘記還有博客這件事了.... 因為之前在造一個簡單的HTTP框架的輪子,裡面用了JSON...當時隨便拉了個FastJSON的庫就用了,然而...嗯,毫無疑問,輪子還是要自己造才好玩,雖然不會在生產環境用,但是寫和不寫多少還是有些差距的 於是今天就造了這個簡單的JSON ...


話說好久沒更新這個博客了

都快忘記還有博客這件事了....

因為之前在造一個簡單的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 }

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.向SharedPreferences 中存儲字元串 2.從SharedPreferences 中獲取存儲的字元串 ...
  • 歡迎探討,如有錯誤敬請指正 如需轉載,請註明出處http://www.cnblogs.com/nullzx/ 1. 簡易版本TimSort排序演算法原理與實現 TimSort排序演算法是Python和Java針對對象數組的預設排序演算法。TimSort排序演算法的本質是歸併排序演算法,只是在歸併排序演算法上進行... ...
  • 什麼是 AIDL AIDL 全稱 Android Interface Definition Language,即 安卓介面描述語言。聽起來很深奧,其實它的本質就是生成進程間通信介面的輔助工具。它的存在形式是一種 .aidl 文件,開發者需要做的就是在該文件中定義進程間通信的介面,編譯的時候 IDE ...
  • 哈夫曼樹的數組實現 (本篇博客是本人第一篇數據結構的博客,有什麼不足還望各位看官指出!!) 題目來源:SOJ 1000. Huffman Coding V1,V3 題目描述 V3: Description 對輸入的英文大寫字母序列進行統計概率,然後構建Huffman樹,得出每個字母的Huffman編 ...
  • 測試與基本規範 為什麼需要測試? 為了穩定性,能夠明確的瞭解是否正確的完成開發。 更加易於維護,能夠在修改代碼後保證功能不被破壞。 集成一些工具,規範開發規範,使得代碼更加穩定( 如通過 phabricator differential 發diff時提交需要執行的單元測試,在開發流程上就可以保證遠端 ...
  • 英文文檔: help([object]) Invoke the built-in help system. (This function is intended for interactive use.) If no argument is given, the interactive help s ...
  • 需求: 1、springmvc返回xml; 技術及環境: 實現: spirngxml的配置主要如下: 添加項目依賴: 實體類JavaBean 一個簡單的JavaBean,添加了JAXB 註解,spring將會根據請求判斷轉換成xml。JAXB不需要添加額外的依賴庫,已經包含在jdk中。 spring ...
  • (1) 編寫一個程式,生成一個10*10的二維隨機整數數組,並將該數組的每行最大值保存於一個一維數組中,將每列平均值保存於另外一個一維數組中並分別輸出。 (2) 編程輸出楊輝三角的前10行。 找出一個,即該位置上的元素在該行上最大,在該列上最小(註:一個二維數組也可能沒有這樣的鞍點)。 /** * ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...