代码在最后

我个人是不太喜欢http和json,可能是游戏做的多了的原因的,对通信协议和通信方式特敏感,因此即使是做应用我也会选择rpc而非http,但是有时候因为各种原因,还是不的不处理标准的http+json的东西。

这一次也确实需要处理一大串json,就是将一大堆的json转换成标准的java pojo。也许小json串我们可以直接用JSONObject去提值就行了,但是如果json是这样:

一个拥有近百个不一样的字段的pojo,如果我们需要单独的去取值估计会疯掉,这还不是主要的,更蛋疼的是pojo本身的属性又是array或者其他pojo,这样依次嵌套,估计我已经疯了。另外还有一个问题就是如果字段名称一修改,就的手动去修改get的那个名称,完全是苦力活。

(ps:上面那个图,是nutch+es返回的值,我自己弄了一个搜索引擎玩,所有返回有大坨的数据,但是我实际处理的不是这个数据,这里只是用它举例,自己搞的搜索引擎在:

http://search.bucry.com/ 纯粹是为了好玩而已)

但是我又不得不面对这个问题,就是把这一大串json弄成pojo,于是我自然想到偷懒,想用一个东西自动的将它封装成pojo,自动识别pojo的字段,自动从json中去取,并且自动调用set赋值,那么即使后面修改了字段名称,又怎样?无所谓,它本身就是反射,于是开始动手做,我需要解决的问题如下:

1.遍历pojo的属性,拿到它的属性的这个变量的名称

2.根据属性的名称,从JSONObject里面去get值

3.在JSONObject里面get值的时候是需要知道变量的类型的,如果它是一个pojo,那么继续递归调用走 1

4.在JSONObject里面get值的时候如果是一个List活着Array那么使用JSONArray,然后通过String取出值,再判断String,递归走2

5.反射调用set方法赋值

6.包装成功

要解决上面的问题,首先我想到的是反射,但是反射在将其反射的时候必须知道类全路径,于是我这个东西有其局限性:

pojo类必须有这个字段:

  1. private String className = RowResponse.class.getName();

也就是服务器在tojson的时候把这个字段传给客户端,客户端在原封不动的传送给服务器,那么就能够成功的通过递归自动封装所有的pojo,有人会说这样多一个字段数据量会增大,会使通信变慢的,这里我想说的是,json已经大到我需要这样去处理pojo的程度了,还管个卵的速度,这一大坨的东西注定它快不了。

首先我们必须有两个方法,一个是处理JSONObject,另一个是处理JSONArray 的,然后它们之间会相互交叉调用,它们本身会相互递归调用

  1. public Object translateFromJson(JSONObject jsonObject) throws Exception {
  2.  
  3. JSONType jsonType = JSONType.JSONOBJECT;
  4. Class<?> baseClass = Class.forName(jsonObject.getString("className"));
  5. Object object = baseClass.newInstance();
  6. Field[] fields = baseClass.getDeclaredFields();
  7.  
  8. for (Field filed : fields) {
  9.  
  10. Class<?> filedType = filed.getType();
  11. Object filedValue = null;
  12. if ("serialVersionUID".equals(filed.getName())) {
  13. continue;
  14. }
  15.  
  16. if (filedType.getCanonicalName().contains("int") || filedType.getCanonicalName().contains("Integer")) {
  17. filedValue = jsonObject.getInt(filed.getName());
  18. } else if (filedType.getCanonicalName().contains("String")) {
  19. filedValue = jsonObject.getString(filed.getName());
  20. } else if (filedType.getCanonicalName().contains("List")) {
  21. jsonType = JSONType.JSONARRAY;
  22. filedValue = jsonObject.getJSONArray(filed.getName());
  23. } else if (filedType.getCanonicalName().contains("Long") || filedType.getCanonicalName().contains("long")) {
  24. filedValue = jsonObject.getLong(filed.getName());
  25. } else if (filedType.getCanonicalName().contains("Double") || filedType.getCanonicalName().contains("double")) {
  26. filedValue = jsonObject.getDouble(filed.getName());
  27. } else if (filedType.getCanonicalName().contains("Boolean") || filedType.getCanonicalName().contains("boolean")) {
  28. filedValue = jsonObject.getBoolean(filed.getName());
  29. } else {
  30. jsonType = JSONType.JSONOBJECT;
  31. filedValue = jsonObject.getJSONObject(filed.getName());
  32. }
  33.  
  34. if (filedValue == null || filedValue.toString().length() == 0) {
  35. continue;
  36. }
  37.  
  38. if (!filedValue.toString().contains("[{") && !filedValue.toString().contains("]}") && !filedValue.toString().contains("className")) {
  39. String firstMethodNameChar = filed.getName().substring(0, 1);
  40. String methodName = "set" + firstMethodNameChar.toUpperCase() + filed.getName().substring(1, filed.getName().length());
  41. Method method = baseClass.getMethod(methodName, filed.getType());
  42. method.invoke(object, filedValue);
  43. } else if (filedValue.toString().contains("className")) {
  44. Object subClassObject = null;
  45. switch (jsonType) {
  46. case JSONARRAY:
  47. subClassObject = translateFromJson((JSONArray)filedValue);
  48. break;
  49. case JSONOBJECT:
  50. subClassObject = translateFromJson((JSONObject)filedValue);
  51. break;
  52. }
  53. String firstMethodNameChar = filed.getName().substring(0, 1);
  54. String methodName = "set" + firstMethodNameChar.toUpperCase() + filed.getName().substring(1, filed.getName().length());
  55. Method method = baseClass.getMethod(methodName, filed.getType());
  56. method.invoke(object, subClassObject);
  57.  
  58. } else {
  59. Object subClassObject = null;
  60. switch (jsonType) {
  61. case JSONARRAY:
  62. subClassObject = translateFromJson((JSONArray)filedValue);
  63. break;
  64. case JSONOBJECT:
  65. subClassObject = translateFromJson((JSONObject)filedValue);
  66. break;
  67. }
  68. String firstMethodNameChar = filed.getName().substring(0, 1);
  69. String methodName = "set" + firstMethodNameChar.toUpperCase() + filed.getName().substring(1, filed.getName().length());
  70. Method method = baseClass.getMethod(methodName, filed.getType());
  71. method.invoke(object, subClassObject);
  72. }
  73. }
  74.  
  75. return object;
  76. }
  1. public Object translateFromJson(JSONArray jsonObject) throws Exception {
  2. List<Object> outputStringList = new LinkedList<Object>();
  3. for(int i=0; i<jsonObject.length(); i++){
  4. String filedValue = jsonObject.get(i).toString();
  5.  
  6. if (filedValue.contains("className")) {
  7. JSONObject jsonObject1 = new JSONObject(filedValue);
  8. outputStringList.add(translateFromJson(jsonObject1));
  9. } else {
  10. outputStringList.add(filedValue);
  11. }
  12. }
  13. return outputStringList;
  14. }

处理过程如下:

1.根据className反射出了这个类的一个实例,由于是进入JSONObjct那么它一定是pojo,否则它就是基本数据类型,是不可能进入该方法的

2.遍历实例的所有属性并且从JSONObject去取值

3.通过反射的getType方法获得对应的类,这里需要区分基本类型与包装类型

4.如果是List那么就走array的方法,如果是JSONObject那么继续递归自己

5.JSONArray直接解析,如果拿出的 String包含className,那么它是pojo继续递归JSONObject,否则结束,直接add成ArrayList<Object>

6.如果是基本数据类型,那么直接通过反射调用set 赋值

7.如果是List,那么在递归后JSONArray会返回一个List<Object> 直接set

到这里,基本搞定了,然后近百号字段也能够自动封装了,反正省去了我一大把的去get值的时间。

点击获取示例代码

(原)编写JAVA工具之json自动封装成pojo的更多相关文章

  1. java将类和函数封装成jar,然后在别的项目中使用这个jar包

    本来想用idea安装的,不过用maven生成后发现jar有20,30M肯定不对,后来还是用eclipse生成了,方便很多 环境: eclipse luna,jdk1.8_112 1.生成jar包,首先 ...

  2. java—将查询的结果封装成List<Map>与用回调函数实现数据的动态封装(44)

    手工的开始QueryRunner类.实现数据封装: MapListHandler MapHandler BeanListHandler BeanHandler 第一步:基本的封装测试 写一个类,Que ...

  3. java将类和函数封装成jar

    本来想用idea安装的,不过用maven生成后发现jar有20,30M肯定不对,后来还是用eclipse生成了,方便很多 环境: eclipse luna,jdk1.8_112 1.生成jar包,首先 ...

  4. 使用HIBERNATE的SQL查询并将结果集自动转换成POJO

    在某些场合下,我们可能想使用HIBERNATE的框架提供的SQL查询接口,但是,由于实体没有做映射,HIBERNATE不能把结果集转换成你想要的List<POJO>,本文讨论如何在这种情况 ...

  5. IDEA 工具从Json自动生成JavaBean

    1.先安装GsonFormat插件:File-->Setting-->Plugins-->GsonFormat-->OK 2.new 一个新的Class空文件,然后 Alt+I ...

  6. (在线工具)JSON字符串转换成Java实体类(POJO)

    http://www.bejson.com/json2javapojo/ 付代码代码转换示例: public static FixMixedOrderResponse serialization(St ...

  7. 使用jquery将表单自动封装成json对象 /json对象元素的添加删除和转换

    $.fn.serializeObject = function () { var o = {}; var a = this.serializeArray(); $.each(a, function ( ...

  8. js使用工具将表单封装成json字符串传到后台,js截取字符串(学生笔记)

    <script src="js/jquery.min.js"></script> <script src="https://cdn.boot ...

  9. [ java 工具类] xml字符串解析成Map(DOM解析)

    package com.tencent.jungle.wechat.util; import com.google.inject.Singleton; import org.w3c.dom.Docum ...

随机推荐

  1. ubuntu安装完整版的vim

    apt-get remove vim-commonapt-get install vim

  2. vue中a的href写法

    注意点:href前面要加“:”或者v-bind: 2.字符串要用单引号“ ’ ”包住 加上了冒号是为了动态绑定数据,等号后面可以写变量. 如果不使用冒号,等号后面就可以写字符串等原始类型数据.这是就无 ...

  3. 【luogu P3378 堆】 模板

    题目链接:https://www.luogu.org/problemnew/show/P3378 是堆的模板...我懒,STL da fa is good #include <iostream& ...

  4. Dubbo源码分析之ExtensionLoader加载过程解析

    ExtensionLoader加载机制阅读: Dubbo的类加载机制是模仿jdk的spi加载机制:  Jdk的SPI扩展加载机制:约定是当服务的提供者每增加一个接口的实现类时,需要在jar包的META ...

  5. java8新特性学习1

    java8增加了不少新特性,下面就一些常见的新特性进行学习... 1.接口中的方法 2.函数式接口 3.Lambda表达式 4.java8内置的四大核心函数式接口 5.方法引用和构造器引用 6.Str ...

  6. RPAD()和LPAD()函数进行字符串的填充

    RPAD()函数从右边对字符串使用指定的字符进行填充. 格式:RPAD(string,padded_length,[pad_string]) string 表示:被填充的字符串. padded_len ...

  7. 在iOS中如何正确的实现行间距与行高

    最近准备给 VirtualView-iOS 的文本元素新增一个 lineHeight 属性,以便和 VirtualView-Android配合时能更精确的保证双平台的一致性.面向 Google 以及 ...

  8. 一站式学习Redis 从入门到高可用分布式实践(慕课)第六章 Redis开发运维常见问题

    fork操作 1.同步操作 2.与内存量息息相关:内存越大,耗时越长(与机器类型有关) 3.info:latest_fork_usec 进程外开销 AOF追加阻塞 不知道哪个命令??? 单机多实例部署 ...

  9. Webpack4 学习笔记六 多页面配置和devtool

    webpack 多页配置 webpack可以配置单页应用, 也可以配置多页应用. 区别在于, 单页应用entry入口只有一个, 而多页应用入口有多个 webpack配置: const path = r ...

  10. Nginx从搭建到配置支持HTTPS

    原文地址:https://www.xingkongbj.com/blog/nginx/nginx.html 安装 基础包 ububtu apt-get install build-essential ...