(原)编写JAVA工具之json自动封装成pojo
代码在最后
我个人是不太喜欢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类必须有这个字段:
private String className = RowResponse.class.getName();
也就是服务器在tojson的时候把这个字段传给客户端,客户端在原封不动的传送给服务器,那么就能够成功的通过递归自动封装所有的pojo,有人会说这样多一个字段数据量会增大,会使通信变慢的,这里我想说的是,json已经大到我需要这样去处理pojo的程度了,还管个卵的速度,这一大坨的东西注定它快不了。
首先我们必须有两个方法,一个是处理JSONObject,另一个是处理JSONArray 的,然后它们之间会相互交叉调用,它们本身会相互递归调用:
public Object translateFromJson(JSONObject jsonObject) throws Exception { JSONType jsonType = JSONType.JSONOBJECT;
Class<?> baseClass = Class.forName(jsonObject.getString("className"));
Object object = baseClass.newInstance();
Field[] fields = baseClass.getDeclaredFields(); for (Field filed : fields) { Class<?> filedType = filed.getType();
Object filedValue = null;
if ("serialVersionUID".equals(filed.getName())) {
continue;
} if (filedType.getCanonicalName().contains("int") || filedType.getCanonicalName().contains("Integer")) {
filedValue = jsonObject.getInt(filed.getName());
} else if (filedType.getCanonicalName().contains("String")) {
filedValue = jsonObject.getString(filed.getName());
} else if (filedType.getCanonicalName().contains("List")) {
jsonType = JSONType.JSONARRAY;
filedValue = jsonObject.getJSONArray(filed.getName());
} else if (filedType.getCanonicalName().contains("Long") || filedType.getCanonicalName().contains("long")) {
filedValue = jsonObject.getLong(filed.getName());
} else if (filedType.getCanonicalName().contains("Double") || filedType.getCanonicalName().contains("double")) {
filedValue = jsonObject.getDouble(filed.getName());
} else if (filedType.getCanonicalName().contains("Boolean") || filedType.getCanonicalName().contains("boolean")) {
filedValue = jsonObject.getBoolean(filed.getName());
} else {
jsonType = JSONType.JSONOBJECT;
filedValue = jsonObject.getJSONObject(filed.getName());
} if (filedValue == null || filedValue.toString().length() == 0) {
continue;
} if (!filedValue.toString().contains("[{") && !filedValue.toString().contains("]}") && !filedValue.toString().contains("className")) {
String firstMethodNameChar = filed.getName().substring(0, 1);
String methodName = "set" + firstMethodNameChar.toUpperCase() + filed.getName().substring(1, filed.getName().length());
Method method = baseClass.getMethod(methodName, filed.getType());
method.invoke(object, filedValue);
} else if (filedValue.toString().contains("className")) {
Object subClassObject = null;
switch (jsonType) {
case JSONARRAY:
subClassObject = translateFromJson((JSONArray)filedValue);
break;
case JSONOBJECT:
subClassObject = translateFromJson((JSONObject)filedValue);
break;
}
String firstMethodNameChar = filed.getName().substring(0, 1);
String methodName = "set" + firstMethodNameChar.toUpperCase() + filed.getName().substring(1, filed.getName().length());
Method method = baseClass.getMethod(methodName, filed.getType());
method.invoke(object, subClassObject); } else {
Object subClassObject = null;
switch (jsonType) {
case JSONARRAY:
subClassObject = translateFromJson((JSONArray)filedValue);
break;
case JSONOBJECT:
subClassObject = translateFromJson((JSONObject)filedValue);
break;
}
String firstMethodNameChar = filed.getName().substring(0, 1);
String methodName = "set" + firstMethodNameChar.toUpperCase() + filed.getName().substring(1, filed.getName().length());
Method method = baseClass.getMethod(methodName, filed.getType());
method.invoke(object, subClassObject);
}
} return object;
}
public Object translateFromJson(JSONArray jsonObject) throws Exception {
List<Object> outputStringList = new LinkedList<Object>();
for(int i=0; i<jsonObject.length(); i++){
String filedValue = jsonObject.get(i).toString(); if (filedValue.contains("className")) {
JSONObject jsonObject1 = new JSONObject(filedValue);
outputStringList.add(translateFromJson(jsonObject1));
} else {
outputStringList.add(filedValue);
}
}
return outputStringList;
}
处理过程如下:
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的更多相关文章
- java将类和函数封装成jar,然后在别的项目中使用这个jar包
本来想用idea安装的,不过用maven生成后发现jar有20,30M肯定不对,后来还是用eclipse生成了,方便很多 环境: eclipse luna,jdk1.8_112 1.生成jar包,首先 ...
- java—将查询的结果封装成List<Map>与用回调函数实现数据的动态封装(44)
手工的开始QueryRunner类.实现数据封装: MapListHandler MapHandler BeanListHandler BeanHandler 第一步:基本的封装测试 写一个类,Que ...
- java将类和函数封装成jar
本来想用idea安装的,不过用maven生成后发现jar有20,30M肯定不对,后来还是用eclipse生成了,方便很多 环境: eclipse luna,jdk1.8_112 1.生成jar包,首先 ...
- 使用HIBERNATE的SQL查询并将结果集自动转换成POJO
在某些场合下,我们可能想使用HIBERNATE的框架提供的SQL查询接口,但是,由于实体没有做映射,HIBERNATE不能把结果集转换成你想要的List<POJO>,本文讨论如何在这种情况 ...
- IDEA 工具从Json自动生成JavaBean
1.先安装GsonFormat插件:File-->Setting-->Plugins-->GsonFormat-->OK 2.new 一个新的Class空文件,然后 Alt+I ...
- (在线工具)JSON字符串转换成Java实体类(POJO)
http://www.bejson.com/json2javapojo/ 付代码代码转换示例: public static FixMixedOrderResponse serialization(St ...
- 使用jquery将表单自动封装成json对象 /json对象元素的添加删除和转换
$.fn.serializeObject = function () { var o = {}; var a = this.serializeArray(); $.each(a, function ( ...
- js使用工具将表单封装成json字符串传到后台,js截取字符串(学生笔记)
<script src="js/jquery.min.js"></script> <script src="https://cdn.boot ...
- [ java 工具类] xml字符串解析成Map(DOM解析)
package com.tencent.jungle.wechat.util; import com.google.inject.Singleton; import org.w3c.dom.Docum ...
随机推荐
- 【[SDOI2008]洞穴勘测】
题目 由于始终保证连通性于是我们可以用\(LCT\)来维护这个森林 三个操作分别是\(link,cut,findroot\) 代码 #include<iostream> #include& ...
- (第三场) A PACM Team 【dp,五维背包】
链接:https://www.nowcoder.com/acm/contest/141/A来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言5242 ...
- 2017.9.5 Java知识点总结
1.*程序的数据操作往往都在内存中操作的,也就是说数据运算都在内存中完成. 2.*什么是变量? --变量就是内存中的一块用来存放数据的存储单元. --变量中的值可变 --我们通过变量名就可以找到内存中 ...
- L1 loss L2 loss
https://www.letslearnai.com/2018/03/10/what-are-l1-and-l2-loss-functions.html http://rishy.github.io ...
- c++ 单引号和双引号
c++中单引号表示一个字符,双引号表示字符串 python中单引号与双引号是一样的
- 手写数字识别的k-近邻算法实现
(本文为原创,请勿在未经允许的情况下转载) 前言 手写字符识别是机器学习的入门问题,k-近邻算法(kNN算法)是机器学习的入门算法.本文将介绍k-近邻算法的原理.手写字符识别问题分析.手写字符识别的k ...
- Entity Framework 六
实体框架中的存储过程: 我们在创建edmx的时候把存储过程勾选了,所以在我们的上下文上中生成了方法. 存储过程为:就是需要显示多个表的字段.以往需要显示多个表的字段都是新建一个类把需要的字段当做属性写 ...
- [Windows]ping itsafe&环境变量
(1)when you ping a computer from itsafe,the ping command should return the local IP address. (2)wind ...
- 工作流,WEB框架,UI组件网络收集整理
工作流,WEB框架,UI组件网络收集整理 在博客园上逛了好多年,随手收录了一些工作流,WEB开发框架,UI组件,现在整理一下与大家分享. 由于个人能力与精力有限,望各位园友在评论中补充,我将全部整理到 ...
- Webpack Tapable原理详解
directory - src - sim ---- 简单的模拟实现 - /.js$/ ---- 使用 代码已上传github, 地址 Detailed Webpack 就像一条生产线, 要经过一系列 ...