你還在為文檔里鋪天蓋地滴變量, 結構復雜的json而煩惱嗎~
寫錯了一個類型,然后各種崩潰
寫錯了一個變量名無法解析
代碼工具來啦~
自動生成javabean類,只要一鍵~
此系列的代碼工具就致力于此,替你完成這些無聊的工作,讓你有更多的精力時間研究新姿勢
使用方法
先將代碼工具導入Eclipse, 該項目為Java Project,注意不是Android Project
1.將json字符串數據復制到項目中的jsonString.txt文件中
(json數據可以從文檔中的json數據示例里,或先運行一遍接口調用代碼打印出來json字符串獲取到)
2.運行代碼工具中的JsonUtils類,其中的main函數中會運行json解析主方法
3.打開JsonBean.java文件,刷新,復制其中自動生成好的javabean類直接使用
補充
如果需要public修飾變量,可以ctrl+F進行全部替換
如果需要生成getter and setter方法,可以右鍵Source-》Generate Getter and Setter進行設置
工具代碼已開源,也可以根據需求自行修改
好了,工具使用到此結束,后面介紹下代碼原理等
原理
項目為一個Java Project
利用Gson工具將字符串樹結構解析出來,然后利用File IO流將bean結構根據需求生成代碼再寫入到文件中
可見項目中源碼,良心注釋,幾乎2行代碼1行注釋
這里也貼出下核心類JsonUtils的代碼
package utils;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import entity.ArrayType;
import entity.Json2JavaElement;
public class JsonUtils {
public static void main(String[] args) {
parseJson2Java();
}
/**
* 將json字符串轉換為對應的javabean
* 用法:
* 將json字符串拷貝至本項目中/Json/JsonString.txt 文件中去,然后調用該方法,
* 就會在本項目中/Json/JsonBean.java中生成一個對應的JavaBean類
* 注意:
* 如果json字符串中有null或者空集合[]這種無法判斷類型的,會統一使用Object類型
*/
public static void parseJson2Java() {
/// 讀取json字符串
String string = FileUtils.readToString(new File(“Json\\JsonString.txt”), “UTF-8”);
// 解析獲取整個json結構集合
JsonParser parser = new JsonParser();
JsonElement element = parser.parse(string);
JsonObject jo = element.getAsJsonObject();
ListjsonBeanTree = getJsonBeanTree(jo);
// 利用獲取到的json結構集合,創建對應的javabean文件內容
String javaBeanStr = createJavaBean(jsonBeanTree);
// 將生成的內容寫入到文件中去
FileUtils.writeString2File(javaBeanStr, new File(“Json\\JsonBean.java”));
}
/**
* 根據解析好的數據創建生成對應的javabean類字符串
*
* @param jsonBeanTree 解析好的數據集合
* @return 生成的javabean類字符串
*/
private static String createJavaBean(ListjsonBeanTree) {
StringBuilder sb = new StringBuilder();
// 是否包含自定義子類
boolean hasCustomeClass = false;
ListcustomClassNames = new ArrayList();
sb.append(“public class JsonBeans {\n”);
// 由于在循環的時候有移除操作,所以使用迭代器遍歷
Iteratoriterator = jsonBeanTree.iterator();
while(iterator.hasNext()) {
Json2JavaElement j2j = iterator.next();
// 保存自定義類名稱至集合中,注意已經包含的不再添加
if(j2j.getCustomClassName() != null && !customClassNames.contains(j2j.getCustomClassName())) {
customClassNames.add(j2j.getCustomClassName());
}
if(j2j.getParentJb() != null) {
// 如果有parent,則為自定義子類,設置標識符不做其他操作
hasCustomeClass = true;
} else {
// 如果不是自定義子類,則根據類型名和控件對象名生成變量申明語句
// private TextView tv_name;
sb.append(“\tprivate ”)
.append(getTypeName(j2j))
.append(“ ”)
.append(j2j.getName())
.append(“;\n”);
// 已經使用的數據會移除,則集合中只會剩下自定義子類相關的元素數據,將在后續的循環中處理
iterator.remove();
}
}
// 設置所有自定義類
if(hasCustomeClass) {
for(String customClassName : customClassNames) {
// 根據名稱申明子類
// /*sub class*/
// public class CustomClass {
sb.append(“\n\t/*sub class*/\n”);
sb.append(“\tpublic class ”)
.append(customClassName)
.append(“ {\n”);
// 循環余下的集合
IteratorcustomIterator = jsonBeanTree.iterator();
while(customIterator.hasNext()) {
Json2JavaElement j2j = customIterator.next();
// 根據當前數據的parent名稱,首字母轉為大寫生成parent的類名
String parentClassName = StringUtils.firstToUpperCase(j2j.getParentJb().getName());
// 如果當前數據屬于本次外層循環需要處理的子類
if(parentClassName.equals(customClassName)) {
// 根據類型名和控件對象名生成變量申明語句
// private TextView tv_name;
sb.append(“\t\tprivate ”)
.append(getTypeName(j2j))
.append(“ ”)
.append(j2j.getName())
.append(“;\n”);
// 已經使用的數據會移除,減少下一次外層循環的遍歷次數
customIterator.remove();
}
}
sb.append(“\t}\n”);
}
}
sb.append(“}”);
return sb.toString();
}
/**
* 遞歸遍歷整個json數據結構,保存至jsonBeans集合中
*
* @param rootJo 根json對象
* @return 解析好的數據集合
*/
private static ListgetJsonBeanTree(JsonObject rootJo) {
jsonBeans = new ArrayList();
recursionJson(rootJo, null);
return jsonBeans;
}
/**
* 保存遞歸獲取到數據的集合
*/
private static ListjsonBeans = new ArrayList();
/**
* 遞歸獲取json數據
*
* @param jo 當前遞歸解析的json對象
* @param parent 已經解析好的上一級數據,無上一級時傳入null
*/
private static void recursionJson(JsonObject jo, Json2JavaElement parent) {
// 循環整個json對象的鍵值對
for (Entry entry : jo.entrySet()) {
// json對象的鍵值對建構為 {“key”:value}
// 其中,值可能是基礎類型,也可能是集合或者對象,先解析為json元素
String name = entry.getKey();
JsonElement je = entry.getValue();
Json2JavaElement j2j = new Json2JavaElement();
j2j.setName(name);
if(parent != null) {
j2j.setParentJb(parent);
}
// 獲取json元素的類型,可能為多種情況,如下
Classtype = getJsonType(je);
if(type == null) {
// 自定義類型
// json鍵值的首字母轉為大寫,作為自定義類名
j2j.setCustomClassName(StringUtils.firstToUpperCase(name));
// ?
j2j.setSouceJo(je.getAsJsonObject());
jsonBeans.add(j2j);
// 自定義類需要繼續遞歸,解析自定義類中的json結構
recursionJson(je.getAsJsonObject(), j2j);
} else if(type.equals(JsonArray.class)) {
// 集合類型
// 重置集合數據,并獲取當前json元素的集合類型信息
deepLevel = 0;
arrayType = new ArrayType();
getJsonArrayType(je.getAsJsonArray());
j2j.setArray(true);
j2j.setArrayDeep(deepLevel);
if(arrayType.getJo() != null) {
j2j.setCustomClassName(StringUtils.firstToUpperCase(name));
// 集合內的末點元素類型為自定義類, 遞歸
recursionJson(arrayType.getJo(), j2j);
} else {
j2j.setType(arrayType.getType());
}
jsonBeans.add(j2j);
} else {
// 其他情況,一般都是String,int等基礎數據類型
j2j.setType(type);
jsonBeans.add(j2j);
}
}
}
/**
* 集合深度,如果是3則為ArrayList》》
*/
private static int deepLevel = 0;
/**
* 集合類型數據,用于保存遞歸獲取到的集合信息
*/
private static ArrayType arrayType = new ArrayType();
/**
* 遞歸獲取集合的深度和類型等信息
*
* @param jsonArray json集合數據
*/
private static void getJsonArrayType(JsonArray jsonArray) {
// 每次遞歸,集合深度+1
deepLevel ++;
if (jsonArray.size() == 0) {
// 如果集合為空,則集合內元素類型無法判斷,直接設為Object
arrayType.setArrayDeep(deepLevel);
arrayType.setType(Object.class);
} else {
// 如果集合非空則取出第一個元素進行判斷
JsonElement childJe = jsonArray.get(0);
// 獲取json元素的類型
Classtype = getJsonType(childJe);
if(type == null) {
// 自定義類型
// 設置整個json對象,用于后續進行進一步解析處理
arrayType.setJo(childJe.getAsJsonObject());
arrayType.setArrayDeep(deepLevel);
} else if (type.equals(JsonArray.class)) {
// 集合類型
// 如果集合里面還是集合,則遞歸本方法
getJsonArrayType(childJe.getAsJsonArray());
} else {
// 其他情況,一般都是String,int等基礎數據類型
arrayType.setArrayDeep(deepLevel);
arrayType.setType(type);
}
}
}
/**
* 獲取json元素的類型
*
* @param je json元素
* @return 類型
*/
private static ClassgetJsonType(JsonElement je) {
Classclazz = null;
if(je.isJsonNull()) {
// 數據為null時,無法獲取類型,則視為object類型
clazz = Object.class;
} else if(je.isJsonPrimitive()) {
// primitive類型為基礎數據類型,如String,int等
clazz = getJsonPrimitiveType(je);
} else if(je.isJsonObject()) {
// 自定義類型參數則返回null,讓json的解析遞歸進行進一步處理
clazz = null;
} else if(je.isJsonArray()) {
// json集合類型
clazz = JsonArray.class;
}
return clazz;
}
/**
* 將json元素中的json基礎類型,轉換為String.class,int.class等具體的類型
*
* @param je json元素
* @return 具體數據類型,無法預估的類型統一視為Object.class類型
*/
private static ClassgetJsonPrimitiveType(JsonElement je) {
Classclazz = Object.class;
JsonPrimitive jp = je.getAsJsonPrimitive();
// json中的類型會將數字集合成一個總的number類型,需要分別判斷
if(jp.isNumber()) {
String num = jp.getAsString();
if(num.contains(“。”)) {
// 如果包含“。”則為小數,先嘗試解析成float,如果失敗則視為double
try {
Float.parseFloat(num);
clazz = float.class;
} catch(NumberFormatException e) {
clazz = double.class;
}
} else {
// 如果不包含“。”則為整數,先嘗試解析成int,如果失敗則視為long
try {
Integer.parseInt(num);
clazz = int.class;
} catch(NumberFormatException e) {
clazz = long.class;
}
}
} else if(jp.isBoolean()) {
clazz = boolean.class;
} else if(jp.isString()) {
clazz = String.class;
}
// json中沒有其他具體類型如byte等
return clazz;
}
/**
* 獲取類型名稱字符串
*
* @param j2j 轉換數據元素
* @return 類型名稱,無法獲取時,默認Object
*/
private static String getTypeName(Json2JavaElement j2j) {
String name = “Object”;
Classtype = j2j.getType();
if(j2j.getCustomClassName() != null && j2j.getCustomClassName().length() 》 0) {
// 自定義類,直接用自定義的名稱customClassName
name = j2j.getCustomClassName();
} else {
// 非自定義類即可以獲取類型,解析類型class的名稱,如String.class就對應String
name = type.getName();
int lastIndexOf = name.lastIndexOf(“。”);
if(lastIndexOf != -1) {
name = name.substring(lastIndexOf + 1);
}
}
// 如果集合深度大于0,則為集合數據,根據深度進行ArrayList嵌套
// 深度為3就是ArrayList
StringBuilder sb = new StringBuilder();
for(int i=0; i
sb.append(“ArrayList《”);
}
sb.append(name);
for(int i=0; i
sb.append(“》”);
}
return sb.toString();
}
}
問題
對于數組數據,其中元素的類型只會取第一個數據進行解析,
如果json字符串中數據內第一個數據不全或者數據為空,即無法獲取
對于此類無法獲取數據值造成無法判斷類型的情況,都默認設為了Object類型
評論