本人大四即將畢業的准程序員(JavaSE、JavaEE、android等)一枚,小項目也做過一點,於是乎一時興起就寫了一些工具。
我會在本博客中陸續發布一些平時可能會用到的工具。
代碼質量可能不是很好,大家多擔待!
代碼或者思路有不妥之處,還希望大牛們能不吝賜教哈!
以下代碼為本人原創,轉載請注明:
本文轉載,來自:http://www.cnblogs.com/tiantianbyconan/archive/2013/02/19/2917433.html
JOJSONBuilder工具類:一鍵把多個域對象數據轉換為JSON格式數據,方便用於數據的傳輸和交互。功能類似於通過Gson來生成Json數據。
源碼如下:

1 package com.wangjie.extrautil.jojsonbuilder; 2 3 import java.lang.reflect.Field; 4 import java.lang.reflect.Method; 5 import java.util.ArrayList; 6 import java.util.Arrays; 7 import java.util.Iterator; 8 import java.util.List; 9 import java.util.Set; 10 11 /** 12 * 13 * @author wangjie 14 * @version 創建時間:2013-2-14 上午10:49:59 15 */ 16 public class JOJSONBuilder { 17 private List<?> list; // 傳入的List數據 18 private StringBuilder result = null; 19 private List<String> includes = null; // 要包含的屬性列表 20 private List<String> excludes = null; // 要排除的屬性列表 21 22 /** 23 * 默認構造方法。<br> 24 * 使用此默認的構造方法之后必須要調用setList()傳入List 25 */ 26 public JOJSONBuilder() { 27 28 } 29 /** 30 * 此構造方法會把list中每項的所有屬性信息都會生成在json中。 31 * @param list 所要生成Json的List數據源 32 */ 33 public JOJSONBuilder(List<?> list) { 34 this.list = list; 35 } 36 /** 37 * 此構造方法提供list中每項屬性信息的<b>包含</b>和<b>排除</b>。<br> 38 * <ol> 39 * <li>使用includes,不使用excludes:只生成在includes中的信息<br> 40 * <li>不使用includes,使用excludes:只生成不在excludes中的信息<br> 41 * <li>既使用includes,又使用exclude(不建議):<br> 42 * - 如果includes中和excludes中的信息不沖突,則生成不在excludes中的信息<br> 43 * - 如果includes中和excludes中的信息沖突(某個屬性都出現在這兩個數組中),則沖突部分的信息還是會生成<br> 44 * <li>includes和excludes都不使用,則會把list中每項的所有屬性信息都會生成在json中 45 * </ol> 46 * @param list 所要生成Json的List數據源。 47 * @param includes 所要包含的屬性名稱數組。 48 * @param excludes 所要排除的屬性名稱數組。 49 */ 50 public JOJSONBuilder(List<?> list, String[] includes, String[] excludes) { 51 this.list = list; 52 this.includes = null == includes || includes.length == 0 ? null : Arrays.asList(includes); 53 this.excludes = null == excludes || excludes.length == 0 ? null : Arrays.asList(excludes); 54 } 55 /** 56 * 獲得正在進行生成json文件的信息來源List。 57 * @author wangjie 58 * @return 返回正在進行生成json文件的信息來源List 59 */ 60 public List<?> getList() { 61 return list; 62 } 63 /** 64 * 可使用此方法來傳入、替換JOJSONBuilder對象中的List對象。 65 * @author wangjie 66 * @param list 所要生成Json的List數據源。 67 * @return 返回當前JOJSONBuilder對象 68 */ 69 public JOJSONBuilder setList(List<?> list) { 70 this.list = list; 71 return this; 72 } 73 /** 74 * 設置包含的屬性信息。 75 * @author wangjie 76 * @param incFieldName 要包含的屬性名 77 * @return 返回當前JOJSONBuilder對象 78 */ 79 public JOJSONBuilder setIncludes(String... incFieldName) { 80 this.includes = null == incFieldName || incFieldName.length == 0 ? null : Arrays.asList(incFieldName); 81 return this; 82 } 83 /** 84 * 設置排除的屬性信息。 85 * @author wangjie 86 * @param excFieldName 要排除的屬性名 87 * @return 返回當前JOJSONBuilder對象 88 */ 89 public JOJSONBuilder setExcludes(String... excFieldName) { 90 this.excludes = null == excFieldName || excFieldName.length == 0 ? null : Arrays.asList(excFieldName); 91 return this; 92 } 93 /** 94 * 獲得指定Class類型的所有屬性,並打印在控制台上。 95 * @author wangjie 96 * @param clazz 要獲取的屬性的類的Class對象。 97 * @return 返回該Class對象的所有屬性。 98 */ 99 public Field[] getFields(Class<?> clazz) { 100 Field[] fields = clazz.getDeclaredFields(); 101 System.out.print("fields of the class that named " + clazz.getName() + ": "); 102 for(Field field : fields){ 103 System.out.print(field.getName() + ", "); 104 } 105 System.out.println(); 106 return fields; 107 } 108 109 /** 110 * 根據list中的對象來生成對應的json文件。 111 * @author wangjie 112 * @return 返回生成的Json字符串。 113 * @throws Exception 如果List檢驗不通過,則拋出異常。 114 */ 115 public StringBuilder jsonBuild() throws Exception{ 116 //檢驗傳入的List是否有效 117 checkValidityList(); 118 //json文件開始生成------------------------- 119 result = new StringBuilder(); 120 jsonSubBuild(list); // 遞歸生成 121 return result; 122 } 123 /** 124 * 生成json可遞歸部分的子數據(根據某些對象組成的List來生成屬性json文件) 125 * @author wangjie 126 * @param list 127 */ 128 private void jsonSubBuild(List<?> list){ 129 // Class<?> clazz = list.get(0).getClass(); // 獲取對應的Class對象 130 Object curObj = null; // 每次循環當前的類對象(資源) 131 int listLength = list.size(); // 類對象個數 132 // String simpleName = clazz.getSimpleName(); // 獲取類名(不含包名) 133 134 result.append("["); // 根標簽開始 135 136 for(int i = 0; i < listLength; i++){ 137 if(i != 0){ 138 result.append(","); 139 } 140 curObj = list.get(i); 141 jsonSubSubBuild(curObj, list); // 子數據遞歸 142 } 143 144 result.append("]"); // 根標簽結束 145 } 146 /** 147 * 生成json可遞歸部分的子子數據(根據某個對象來生成屬性json文件) 148 * @author wangjie 149 * @param curObj 要生成json文件的那個對象 150 * @param list curObj參數屬於的那個List 151 */ 152 private void jsonSubSubBuild(Object curObj, List<?> list){ 153 String fieldName = ""; // 每次要調用的屬性名 154 String methodName = ""; // 每次要調用的方法名 155 Method method = null;; // 每次要調用的方法 156 Object value = ""; // 每次要獲得的屬性值(子標簽) 157 158 Class<?> clazz = curObj.getClass(); 159 Field[] fields = getFields(clazz); // 獲得對應類型的所有變量 160 int fieldsLength = fields.length; // 類對象的屬性數量 161 162 result.append("{"); 163 int offset = 0; // 包含的第一個屬性偏移量 164 int temp = 0; 165 for(int j = 0; j < fieldsLength; j++){ 166 fieldName = fields[j].getName(); // 獲取對應屬性名 167 168 if(list == this.list){ // 只在最外層的類的屬性中進行排除包含 169 // 使用includes,不使用excludes:只生成在includes中的信息 170 if(null != includes && null == excludes){ 171 if(!includes.contains(fieldName)){ 172 continue; 173 } 174 } 175 176 //不使用includes,使用excludes:只生成不在excludes中的信息 177 if(null == includes && null != excludes){ // 只使用了不包含 178 if(excludes.contains(fieldName)){ 179 continue; 180 } 181 } 182 183 //既使用includes,又使用exclude(不建議): 184 //- 如果includes中和excludes中的信息不沖突,則生成不在excludes中的信息 185 //- 如果includes中和excludes中的信息沖突(某個屬性都出現在這兩個數組中),則沖突部分的信息還是會生成 186 if(null != includes && null != excludes){ // 既使用了包含,又使用了不包含 187 if(!includes.contains(fieldName) && excludes.contains(fieldName)){ 188 continue; 189 } 190 } 191 // 記錄第一個包含的屬性的索引 192 if(0 == temp){ 193 offset = j; 194 temp++; 195 } 196 // offset = 0 == temp++ ? j : 0; 197 } 198 199 methodName = getGetterMethodNameByFieldName(fields[j]); 200 try { 201 method = clazz.getDeclaredMethod(methodName, new Class[]{}); 202 method.setAccessible(true); 203 value = method.invoke(curObj, new Object[]{}); 204 //********************************************************* 205 if(j != offset){ // 第一個屬性前面不加"," 206 result.append(","); 207 } 208 result.append("'" + fieldName + "':"); 209 if(fields[j].getType() == List.class){ // 如果屬性是List類型 210 List<?> subList = (List<?>)value; 211 jsonSubBuild(subList); // 子數據遞歸 212 }else if(fields[j].getType() == Set.class){ // 如果屬性是Set類型的 213 Set<?> subSet = (Set<?>)value; 214 Iterator<?> iter = subSet.iterator(); 215 List<Object> subList = new ArrayList<Object>(); 216 while(iter.hasNext()){ 217 subList.add(iter.next()); 218 } 219 jsonSubBuild(subList); // 子數據遞歸 220 } 221 // 如果ClassLoader不是null表示該類不是啟動類加載器加載的,不是Java API的類,是自己寫的java類 222 else if(null != fields[j].getType().getClassLoader()){ 223 jsonSubSubBuild(value, null); // 子子數據遞歸 224 } 225 else{ // 其它類型都認為是普通文本類型 226 // 添加子元素(類屬性)標簽 227 if(value.getClass() == String.class){ 228 result.append("'" + value + "'"); 229 }else{ 230 result.append(value.toString()); 231 } 232 233 } 234 235 //********************************************************* 236 } catch (Exception e) { 237 e.printStackTrace(); 238 } 239 240 } 241 result.append("}"); 242 } 243 244 /** 245 * <ol>通過屬性Field對象來獲取getter方法的方法名。<br> 246 * 如果是boolean或Boolean類型(正則表達式來判斷):isBorrow-->isBorrow();isborrow-->isIsborrow();<br> 247 * 否則:borrow-->getBorrow(); 248 * </ol> 249 * @author wangjie 250 * @param field 要生成getter方法的對應屬性對象。 251 * @return 返回getter方法的方法名。 252 */ 253 private String getGetterMethodNameByFieldName(Field field){ 254 String methodName = null; 255 String fieldName = field.getName(); 256 // 解析屬性對應的getter方法名 257 // 判斷是否是boolean或Boolean類型:isBorrow-->isBorrow();isborrow-->isIsborrow() 258 if(field.getType() == boolean.class || field.getType() == Boolean.class){ 259 if(fieldName.matches("^is[A-Z].*")){ 260 methodName = fieldName; 261 }else{ 262 methodName = "is" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); 263 } 264 }else{ 265 methodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); 266 } 267 return methodName; 268 } 269 270 /** 271 * 檢驗傳入的List的合法性(List是不是為null、長度是不是為0、是不是每項都是同一個類型) 272 * @author wangjie 273 * @throws Exception 如果List為null, 或者長度為, 或者每項不是同一個類型, 拋出異常 274 */ 275 private void checkValidityList() throws Exception{ 276 if(null == list){ 277 throw new Exception("請保證傳入的List不為null"); 278 } 279 int size = list.size(); 280 if(list.size() == 0){ 281 throw new Exception("請保證傳入的List長度不為0"); 282 } 283 for(int i = 1; i < size; i++){ 284 if(list.get(0).getClass() != list.get(i).getClass()){ 285 throw new Exception("請保證傳入的List每項都是同一個類型"); 286 } 287 } 288 289 } 290 291 292 293 }
使用方法如下:
例如:
Student類(該類有屬性name,age,isBoy,books等屬性;其中books屬性是一個List,存放Book對象):
1 private String name; 2 private int age; 3 private boolean isBoy; 4 private List<Book> books; 5 //並實現getter和setter方法;
Book類(該類有屬性name,author,number,length,width,isBorrowed等屬性):
1 private String name; 2 private String author; 3 private int number; 4 private float length; 5 private float width; 6 private boolean isBorrowed; 7 //並實現getter和setter方法;
現在有一個List<Student>類型的數據,通過以下代碼把該List轉換為Json:
List<Student> list = new ArrayList<Student>(); //構建幾個Student對象,放入list中 //…… //完整數據版(不使用includes和excludes) JOJSONBuilder jsonBuilder = new JOJSONBuilder(list); String content = jsonBuilder.jsonBuild().toString(); //或者使用包括/排除: JOJSONBuilder jsonBuilder = new JOJSONBuilder(list, new String[]{"name", "age"}, null); jsonBuilder.jsonBuild().toString(); //或者使用方法鏈風格: new JOJSONBuilder().setExcludes("name", "age").jsonBuild().toString();
轉換之后的Json(完整數據版(不使用includes和excludes)):
1 [ 2 { 3 'name':'hello', 4 'age':23, 5 'isBoy':true, 6 'books':[ 7 { 8 'name':'book1', 9 'author':'author1', 10 'number':123, 11 'length':23.5, 12 'width':18.0, 13 'isBorrowed':true 14 }, 15 { 16 'name':'book2', 17 'author':'author2', 18 'number':43, 19 'length':42.23, 20 'width':30.57, 21 'isBorrowed':false 22 } 23 ] 24 }, 25 26 { 27 'name':'world', 28 'age':22, 29 'isBoy':false, 30 'books':[ 31 { 32 'name':'book1', 33 'author':'author1', 34 'number':123, 35 'length':23.5, 36 'width':18.0, 37 'isBorrowed':true 38 }, 39 { 40 'name':'book3', 41 'author':'author3', 42 'number':875, 43 'length':20.59, 44 'width':15.08, 45 'isBorrowed':false 46 }, 47 { 48 'name':'book4', 49 'author':'author4', 50 'number':165, 51 'length':22.75, 52 'width':19.61, 53 'isBorrowed':true 54 } 55 ] 56 } 57 ]