你还在为文档里铺天盖地滴变量, 结构复杂的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类型
『本文转载自网络,64体育的版权归原作者所有,如有侵权请联系删除』