自动根据json字符串生成javabean类

187 篇文章 0 订阅
29 篇文章 0 订阅

转自: http://www.eoeandroid.com/thread-911859-1-1.html?_dsign=110b1075


你还在为文档里铺天盖地滴变量, 结构复杂的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进行设置



工具代码已开源,也可以根据需求自行修改

Github地址
https://github.com/boredream/CodeUtils
欢迎star 和 folk,除了这里的json解析工具还有其他功能
后续还会一直提供不同新功能,大家有需求也可以提出,特别常用的都会找时间尽量添加

回复可见是希望帖子顶上去更多人能看到,希望理解

好了,工具使用到此结束,后面介绍下代码原理等

----------------------------------------------------------------------

原理
项目为一个Java Project
利用Gson工具将字符串树结构解析出来,然后利用File IO流将bean结构根据需求生成代码再写入到文件中

可见项目中源码,良心注释,几乎2行代码1行注释
这里也贴出下核心类JsonUtils的代码

  1. package utils;

  2. import java.io.File;
  3. import java.util.ArrayList;
  4. import java.util.Iterator;
  5. import java.util.List;
  6. import java.util.Map.Entry;

  7. import com.google.gson.JsonArray;
  8. import com.google.gson.JsonElement;
  9. import com.google.gson.JsonObject;
  10. import com.google.gson.JsonParser;
  11. import com.google.gson.JsonPrimitive;

  12. import entity.ArrayType;
  13. import entity.Json2JavaElement;

  14. public class JsonUtils {
  15.     
  16.      public static void main(String[] args) {
  17.           parseJson2Java();
  18.      }
  19.     
  20.      /**
  21.      * 将json字符串转换为对应的javabean
  22.      *
  23.      * <p>
  24.      * 用法:<br>
  25.      * 将json字符串拷贝至本项目中/Json/JsonString.txt 文件中去,然后调用该方法,<br>
  26.      * 就会在本项目中/Json/JsonBean.java中生成一个对应的JavaBean类<br><br>
  27.      * 注意:<br>
  28.      * 如果json字符串中有null或者空集合[]这种无法判断类型的,会统一使用Object类型
  29.      */
  30.      public static void parseJson2Java() {
  31.           /// 读取json字符串
  32.           String string = FileUtils.readToString(new File("Json\\JsonString.txt"), "UTF-8");
  33.          
  34.           // 解析获取整个json结构集合
  35.           JsonParser parser = new JsonParser();
  36.           JsonElement element = parser.parse(string);
  37.           JsonObject jo = element.getAsJsonObject();
  38.           List<Json2JavaElement> jsonBeanTree = getJsonBeanTree(jo);
  39.          
  40.           // 利用获取到的json结构集合,创建对应的javabean文件内容
  41.           String javaBeanStr = createJavaBean(jsonBeanTree);
  42.          
  43.           // 将生成的内容写入到文件中去
  44.           FileUtils.writeString2File(javaBeanStr, new File("Json\\JsonBean.java"));
  45.      }
  46.     
  47.      /**
  48.      * 根据解析好的数据创建生成对应的javabean类字符串
  49.      *
  50.      * @param jsonBeanTree 解析好的数据集合
  51.      * @return 生成的javabean类字符串
  52.      */
  53.      private static String createJavaBean(List<Json2JavaElement> jsonBeanTree) {
  54.           StringBuilder sb = new StringBuilder();
  55.          
  56.           // 是否包含自定义子类
  57.           boolean hasCustomeClass = false;
  58.           List<String> customClassNames = new ArrayList<String>();
  59.          
  60.           sb.append("public class JsonBeans {\n");
  61.          
  62.           // 由于在循环的时候有移除操作,所以使用迭代器遍历
  63.           Iterator<Json2JavaElement> iterator = jsonBeanTree.iterator();
  64.           while(iterator.hasNext()) {
  65.                Json2JavaElement j2j = iterator.next();
  66.               
  67.                // 保存自定义类名称至集合中,注意已经包含的不再添加
  68.                if(j2j.getCustomClassName() != null && !customClassNames.contains(j2j.getCustomClassName())) {
  69.                     customClassNames.add(j2j.getCustomClassName());
  70.                }
  71.               
  72.                if(j2j.getParentJb() != null) {
  73.                     // 如果有parent,则为自定义子类,设置标识符不做其他操作
  74.                     hasCustomeClass = true;
  75.                } else {
  76.                     // 如果不是自定义子类,则根据类型名和控件对象名生成变量申明语句
  77.                     // private TextView tv_name;
  78.                     sb.append("\tprivate ")
  79.                          .append(getTypeName(j2j))
  80.                          .append(" ")
  81.                          .append(j2j.getName())
  82.                          .append(";\n");
  83.                    
  84.                     // 已经使用的数据会移除,则集合中只会剩下自定义子类相关的元素数据,将在后续的循环中处理
  85.                     iterator.remove();
  86.                }
  87.           }
  88.          
  89.           // 设置所有自定义类
  90.           if(hasCustomeClass) {
  91.                for(String customClassName : customClassNames) {
  92.                     // 根据名称申明子类
  93.                    
  94.                     // /*sub class*/
  95.                     // public class CustomClass {
  96.                     sb.append("\n\t/*sub class*/\n");
  97.                     sb.append("\tpublic class ")
  98.                          .append(customClassName)
  99.                          .append(" {\n");
  100.                    
  101.                     // 循环余下的集合
  102.                     Iterator<Json2JavaElement> customIterator = jsonBeanTree.iterator();
  103.                     while(customIterator.hasNext()) {
  104.                          Json2JavaElement j2j = customIterator.next();
  105.                         
  106.                          // 根据当前数据的parent名称,首字母转为大写生成parent的类名
  107.                          String parentClassName = StringUtils.firstToUpperCase(j2j.getParentJb().getName());
  108.                         
  109.                          // 如果当前数据属于本次外层循环需要处理的子类
  110.                          if(parentClassName.equals(customClassName)) {
  111.                               // 根据类型名和控件对象名生成变量申明语句
  112.                               // private TextView tv_name;
  113.                               sb.append("\t\tprivate ")
  114.                                    .append(getTypeName(j2j))
  115.                                    .append(" ")
  116.                                    .append(j2j.getName())
  117.                                    .append(";\n");
  118.                              
  119.                               // 已经使用的数据会移除,减少下一次外层循环的遍历次数
  120.                               customIterator.remove();
  121.                          }
  122.                     }
  123.                     sb.append("\t}\n");
  124.                }
  125.           }
  126.          
  127.           sb.append("}");
  128.           return sb.toString();
  129.      }
  130.     
  131.      /**
  132.      *  递归遍历整个json数据结构,保存至jsonBeans集合中
  133.      * 
  134.      *  @param rootJo 根json对象
  135.      *  @return 解析好的数据集合
  136.      */
  137.      private static List<Json2JavaElement> getJsonBeanTree(JsonObject rootJo) {
  138.           jsonBeans = new ArrayList<Json2JavaElement>();
  139.           recursionJson(rootJo, null);
  140.           return jsonBeans;
  141.      }
  142.     
  143.      /**
  144.      * 保存递归获取到数据的集合
  145.      */
  146.      private static List<Json2JavaElement> jsonBeans = new ArrayList<Json2JavaElement>();
  147.      /**
  148.      * 递归获取json数据
  149.      *
  150.      * @param jo 当前递归解析的json对象
  151.      * @param parent 已经解析好的上一级数据,无上一级时传入null
  152.      */
  153.      private static void recursionJson(JsonObject jo, Json2JavaElement parent) {
  154.           // 循环整个json对象的键值对
  155.           for (Entry<String, JsonElement> entry : jo.entrySet()) {
  156.                // json对象的键值对建构为 {"key":value}
  157.                // 其中,值可能是基础类型,也可能是集合或者对象,先解析为json元素
  158.                String name = entry.getKey();
  159.                JsonElement je = entry.getValue();
  160.               
  161.                Json2JavaElement j2j = new Json2JavaElement();
  162.                j2j.setName(name);
  163.                if(parent != null) {
  164.                     j2j.setParentJb(parent);
  165.                }
  166.               
  167.                // 获取json元素的类型,可能为多种情况,如下
  168.                Class<?> type = getJsonType(je);
  169.                if(type == null) {
  170.                     // 自定义类型
  171.                    
  172.                     // json键值的首字母转为大写,作为自定义类名
  173.                     j2j.setCustomClassName(StringUtils.firstToUpperCase(name));
  174.                     // ?
  175.                     j2j.setSouceJo(je.getAsJsonObject());
  176.                     jsonBeans.add(j2j);
  177.                    
  178.                     // 自定义类需要继续递归,解析自定义类中的json结构
  179.                     recursionJson(je.getAsJsonObject(), j2j);
  180.                } else if(type.equals(JsonArray.class)) {
  181.                     // 集合类型
  182.                    
  183.                     // 重置集合数据,并获取当前json元素的集合类型信息
  184.                     deepLevel = 0;
  185.                     arrayType = new ArrayType();
  186.                     getJsonArrayType(je.getAsJsonArray());
  187.                    
  188.                     j2j.setArray(true);
  189.                     j2j.setArrayDeep(deepLevel);
  190.                    
  191.                     if(arrayType.getJo() != null) {
  192.                          j2j.setCustomClassName(StringUtils.firstToUpperCase(name));
  193.                          // 集合内的末点元素类型为自定义类, 递归
  194.                          recursionJson(arrayType.getJo(), j2j);
  195.                     } else {
  196.                          j2j.setType(arrayType.getType());
  197.                     }
  198.                     jsonBeans.add(j2j);
  199.                } else {
  200.                     // 其他情况,一般都是String,int等基础数据类型
  201.                    
  202.                     j2j.setType(type);
  203.                     jsonBeans.add(j2j);
  204.                }
  205.           }
  206.      }
  207.     
  208.      /**
  209.      * 集合深度,如果是3则为ArrayList<ArrayList<ArrayList<>>>
  210.      */
  211.      private static int deepLevel = 0;
  212.      /**
  213.      * 集合类型数据,用于保存递归获取到的集合信息
  214.      */
  215.      private static ArrayType arrayType = new ArrayType();
  216.      /**
  217.      * 递归获取集合的深度和类型等信息
  218.      *
  219.      * @param jsonArray json集合数据
  220.      */
  221.      private static void getJsonArrayType(JsonArray jsonArray) {
  222.           // 每次递归,集合深度+1
  223.           deepLevel ++;
  224.          
  225.           if (jsonArray.size() == 0) {
  226.                // 如果集合为空,则集合内元素类型无法判断,直接设为Object
  227.                arrayType.setArrayDeep(deepLevel);
  228.                arrayType.setType(Object.class);
  229.           } else {
  230.                // 如果集合非空则取出第一个元素进行判断
  231.                JsonElement childJe = jsonArray.get(0);
  232.               
  233.                // 获取json元素的类型
  234.                Class<?> type = getJsonType(childJe);
  235.               
  236.                if(type == null) {
  237.                     // 自定义类型
  238.                    
  239.                     // 设置整个json对象,用于后续进行进一步解析处理
  240.                     arrayType.setJo(childJe.getAsJsonObject());
  241.                     arrayType.setArrayDeep(deepLevel);
  242.                } else if (type.equals(JsonArray.class)) {
  243.                     // 集合类型
  244.                    
  245.                     // 如果集合里面还是集合,则递归本方法
  246.                     getJsonArrayType(childJe.getAsJsonArray());
  247.                } else {
  248.                     // 其他情况,一般都是String,int等基础数据类型
  249.                    
  250.                     arrayType.setArrayDeep(deepLevel);
  251.                     arrayType.setType(type);
  252.                }
  253.           }
  254.      }
  255.     
  256.      /**
  257.      * 获取json元素的类型
  258.      *
  259.      * @param je json元素
  260.      * @return 类型
  261.      */
  262.      private static Class<?> getJsonType(JsonElement je) {
  263.           Class<?> clazz = null;
  264.          
  265.           if(je.isJsonNull()) {
  266.                // 数据为null时,无法获取类型,则视为object类型
  267.                clazz = Object.class;
  268.           } else if(je.isJsonPrimitive()) {
  269.                // primitive类型为基础数据类型,如String,int等
  270.                clazz = getJsonPrimitiveType(je);
  271.           } else if(je.isJsonObject()) {
  272.                // 自定义类型参数则返回null,让json的解析递归进行进一步处理
  273.                clazz = null;
  274.           } else if(je.isJsonArray()) {
  275.                // json集合类型
  276.                clazz = JsonArray.class;
  277.           }
  278.           return clazz;
  279.      }

  280.      /**
  281.      * 将json元素中的json基础类型,转换为String.class,int.class等具体的类型
  282.      *
  283.      * @param je json元素
  284.      * @return 具体数据类型,无法预估的类型统一视为Object.class类型
  285.      */
  286.      private static Class<?> getJsonPrimitiveType(JsonElement je) {
  287.           Class<?> clazz = Object.class;
  288.           JsonPrimitive jp = je.getAsJsonPrimitive();
  289.           // json中的类型会将数字集合成一个总的number类型,需要分别判断
  290.           if(jp.isNumber()) {
  291.                String num = jp.getAsString();
  292.                if(num.contains(".")) {
  293.                     // 如果包含"."则为小数,先尝试解析成float,如果失败则视为double
  294.                     try {
  295.                          Float.parseFloat(num);
  296.                          clazz = float.class;
  297.                     } catch(NumberFormatException e) {
  298.                          clazz = double.class;
  299.                     }
  300.                } else {
  301.                     // 如果不包含"."则为整数,先尝试解析成int,如果失败则视为long
  302.                     try {
  303.                          Integer.parseInt(num);
  304.                          clazz = int.class;
  305.                     } catch(NumberFormatException e) {
  306.                          clazz = long.class;
  307.                     }
  308.                }
  309.           } else if(jp.isBoolean()) {
  310.                clazz = boolean.class;
  311.           } else if(jp.isString()) {
  312.                clazz = String.class;
  313.           }
  314.           // json中没有其他具体类型如byte等
  315.           return clazz;
  316.      }
  317.     
  318.      /**
  319.      * 获取类型名称字符串
  320.      *
  321.      * @param j2j 转换数据元素
  322.      * @return 类型名称,无法获取时,默认Object
  323.      */
  324.      private static String getTypeName(Json2JavaElement j2j) {
  325.           String name = "Object";
  326.          
  327.           Class<?> type = j2j.getType();
  328.           if(j2j.getCustomClassName() != null && j2j.getCustomClassName().length() > 0) {
  329.                // 自定义类,直接用自定义的名称customClassName
  330.                name = j2j.getCustomClassName();
  331.           } else {
  332.                // 非自定义类即可以获取类型,解析类型class的名称,如String.class就对应String
  333.                name = type.getName();
  334.                int lastIndexOf = name.lastIndexOf(".");
  335.                if(lastIndexOf != -1) {
  336.                     name = name.substring(lastIndexOf + 1);
  337.                }
  338.           }

  339.           // 如果集合深度大于0,则为集合数据,根据深度进行ArrayList嵌套
  340.           // 深度为3就是ArrayList<ArrayList<ArrayList<type>>>
  341.           StringBuilder sb = new StringBuilder();
  342.           for(int i=0; i<j2j.getArrayDeep(); i++) {
  343.                sb.append("ArrayList<");
  344.           }
  345.           sb.append(name);
  346.           for(int i=0; i<j2j.getArrayDeep(); i++) {
  347.                sb.append(">");
  348.           }
  349.           return sb.toString();
  350.      }
  351. }
复制代码



----------------------------------------------------------------------

问题
对于数组数据,其中元素的类型只会取第一个数据进行解析,
如果json字符串中数据内第一个数据不全或者数据为空,即无法获取
对于此类无法获取数据值造成无法判断类型的情况,都默认设为了Object类型

----------------------------------------------------------------------

欢迎Github上star和follow, 多个高质量源码等待着你
也可以在eoeandroid论坛主页中进入我个人中心,查看我其他主题帖子,篇篇高质量,你值得信赖

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值