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