[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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...