[工具库]JOJSONBuilder工具类——一键把多个bean对象数据转换为JSON格式数据

本人大四即将毕业的准程序员(JavaSE、JavaEE、android等)一枚,小项目也做过一点,于是乎一时兴起就写了一些工具。

我会在本博客中陆续发布一些平时可能会用到的工具。

代码质量可能不是很好,大家多担待!

代码或者思路有不妥之处,还希望大牛们能不吝赐教哈!

 

以下代码为本人原创,转载请注明:

本文转载,来自:http://www.cnblogs.com/tiantianbyconan/archive/2013/02/19/2917433.html

 

JOJSONBuilder工具类:一键把多个域对象数据转换为JSON格式数据,方便用于数据的传输和交互。功能类似于通过Gson来生成Json数据。

源码如下:

View Code
  1 package com.wangjie.extrautil.jojsonbuilder;
  2 
  3 import java.lang.reflect.Field;
  4 import java.lang.reflect.Method;
  5 import java.util.ArrayList;
  6 import java.util.Arrays;
  7 import java.util.Iterator;
  8 import java.util.List;
  9 import java.util.Set;
 10 
 11 /**
 12  * 
 13  * @author wangjie
 14  * @version 创建时间:2013-2-14 上午10:49:59
 15  */
 16 public class JOJSONBuilder {
 17     private List<?> list; // 传入的List数据
 18     private StringBuilder result = null;
 19     private List<String> includes = null; // 要包含的属性列表
 20     private List<String> excludes = null; // 要排除的属性列表
 21     
 22     /**
 23      * 默认构造方法。<br>
 24      * 使用此默认的构造方法之后必须要调用setList()传入List
 25      */
 26     public JOJSONBuilder() {
 27         
 28     }
 29     /**
 30      * 此构造方法会把list中每项的所有属性信息都会生成在json中。
 31      * @param list 所要生成Json的List数据源
 32      */
 33     public JOJSONBuilder(List<?> list) {
 34         this.list = list;
 35     }
 36     /**
 37      * 此构造方法提供list中每项属性信息的<b>包含</b>和<b>排除</b>。<br>
 38      * <ol>
 39      * <li>使用includes,不使用excludes:只生成在includes中的信息<br>
 40      * <li>不使用includes,使用excludes:只生成不在excludes中的信息<br>
 41      * <li>既使用includes,又使用exclude(不建议):<br>
 42      *  - 如果includes中和excludes中的信息不冲突,则生成不在excludes中的信息<br>
 43      *  - 如果includes中和excludes中的信息冲突(某个属性都出现在这两个数组中),则冲突部分的信息还是会生成<br>
 44      * <li>includes和excludes都不使用,则会把list中每项的所有属性信息都会生成在json中
 45      * </ol>
 46      * @param list 所要生成Json的List数据源。
 47      * @param includes 所要包含的属性名称数组。
 48      * @param excludes 所要排除的属性名称数组。
 49      */
 50     public JOJSONBuilder(List<?> list, String[] includes, String[] excludes) {
 51         this.list = list;
 52         this.includes = null == includes || includes.length == 0 ? null : Arrays.asList(includes);
 53         this.excludes = null == excludes || excludes.length == 0 ? null : Arrays.asList(excludes);
 54     }
 55     /**
 56      * 获得正在进行生成json文件的信息来源List。
 57      * @author wangjie
 58      * @return 返回正在进行生成json文件的信息来源List
 59      */
 60     public List<?> getList() {
 61         return list;
 62     }
 63     /**
 64      * 可使用此方法来传入、替换JOJSONBuilder对象中的List对象。
 65      * @author wangjie
 66      * @param list 所要生成Json的List数据源。
 67      * @return 返回当前JOJSONBuilder对象
 68      */
 69     public JOJSONBuilder setList(List<?> list) {
 70         this.list = list;
 71         return this;
 72     }
 73     /**
 74      * 设置包含的属性信息。
 75      * @author wangjie
 76      * @param incFieldName 要包含的属性名
 77      * @return 返回当前JOJSONBuilder对象
 78      */
 79     public JOJSONBuilder setIncludes(String... incFieldName) {
 80         this.includes = null == incFieldName || incFieldName.length == 0 ? null : Arrays.asList(incFieldName);
 81         return this;
 82     }
 83     /**
 84      * 设置排除的属性信息。
 85      * @author wangjie
 86      * @param excFieldName 要排除的属性名
 87      * @return 返回当前JOJSONBuilder对象
 88      */
 89     public JOJSONBuilder setExcludes(String... excFieldName) {
 90         this.excludes = null == excFieldName || excFieldName.length == 0 ? null : Arrays.asList(excFieldName);
 91         return this;
 92     }
 93     /**
 94      * 获得指定Class类型的所有属性,并打印在控制台上。
 95      * @author wangjie
 96      * @param clazz 要获取的属性的类的Class对象。
 97      * @return 返回该Class对象的所有属性。
 98      */
 99     public Field[] getFields(Class<?> clazz) {
100         Field[] fields = clazz.getDeclaredFields();
101         System.out.print("fields of the class that named " + clazz.getName() + ": ");
102         for(Field field : fields){
103             System.out.print(field.getName() + ", ");
104         }
105         System.out.println();
106         return fields;
107     }
108     
109     /**
110      * 根据list中的对象来生成对应的json文件。
111      * @author wangjie
112      * @return 返回生成的Json字符串。
113      * @throws Exception 如果List检验不通过,则抛出异常。
114      */
115     public StringBuilder jsonBuild() throws Exception{
116         //检验传入的List是否有效
117         checkValidityList();
118         //json文件开始生成-------------------------
119         result = new StringBuilder();
120         jsonSubBuild(list); // 递归生成
121         return result;
122     }
123     /**
124      * 生成json可递归部分的子数据(根据某些对象组成的List来生成属性json文件)
125      * @author wangjie
126      * @param list 
127      */
128     private void jsonSubBuild(List<?> list){
129 //        Class<?> clazz = list.get(0).getClass(); // 获取对应的Class对象
130         Object curObj = null; // 每次循环当前的类对象(资源)
131         int listLength = list.size(); // 类对象个数
132 //        String simpleName = clazz.getSimpleName(); // 获取类名(不含包名)
133         
134         result.append("["); // 根标签开始
135         
136         for(int i = 0; i < listLength; i++){
137             if(i != 0){
138                 result.append(",");
139             }
140             curObj = list.get(i);
141             jsonSubSubBuild(curObj, list); // 子数据递归
142         }
143         
144         result.append("]"); // 根标签结束
145     }
146     /**
147      * 生成json可递归部分的子子数据(根据某个对象来生成属性json文件)
148      * @author wangjie
149      * @param curObj 要生成json文件的那个对象 
150      * @param list curObj参数属于的那个List
151      */
152     private void jsonSubSubBuild(Object curObj, List<?> list){
153         String fieldName = ""; // 每次要调用的属性名
154         String methodName = ""; // 每次要调用的方法名
155         Method method = null;; // 每次要调用的方法
156         Object value = ""; // 每次要获得的属性值(子标签)
157         
158         Class<?> clazz = curObj.getClass();
159         Field[] fields = getFields(clazz); // 获得对应类型的所有变量
160         int fieldsLength = fields.length; // 类对象的属性数量
161         
162         result.append("{");
163         int offset = 0; // 包含的第一个属性偏移量
164         int temp = 0;
165         for(int j = 0; j < fieldsLength; j++){
166             fieldName = fields[j].getName(); // 获取对应属性名
167             
168             if(list == this.list){ // 只在最外层的类的属性中进行排除包含
169                 // 使用includes,不使用excludes:只生成在includes中的信息
170                 if(null != includes && null == excludes){
171                     if(!includes.contains(fieldName)){
172                         continue;
173                     }
174                 }
175                 
176                 //不使用includes,使用excludes:只生成不在excludes中的信息
177                 if(null == includes && null != excludes){ // 只使用了不包含
178                     if(excludes.contains(fieldName)){
179                         continue;
180                     }
181                 }
182                 
183                 //既使用includes,又使用exclude(不建议):
184                 //- 如果includes中和excludes中的信息不冲突,则生成不在excludes中的信息
185                 //- 如果includes中和excludes中的信息冲突(某个属性都出现在这两个数组中),则冲突部分的信息还是会生成
186                 if(null != includes && null != excludes){ // 既使用了包含,又使用了不包含
187                     if(!includes.contains(fieldName) && excludes.contains(fieldName)){
188                         continue;
189                     }
190                 }
191                 // 记录第一个包含的属性的索引
192                 if(0 == temp){
193                     offset = j;
194                     temp++;
195                 }
196 //                offset = 0 == temp++ ? j : 0;
197             }
198             
199             methodName = getGetterMethodNameByFieldName(fields[j]);
200             try {
201                 method = clazz.getDeclaredMethod(methodName, new Class[]{});
202                 method.setAccessible(true);
203                 value = method.invoke(curObj, new Object[]{});
204                 //*********************************************************
205                 if(j != offset){ // 第一个属性前面不加","
206                     result.append(",");
207                 }
208                 result.append("'" + fieldName + "':");
209                 if(fields[j].getType() == List.class){ // 如果属性是List类型
210                     List<?> subList = (List<?>)value;
211                     jsonSubBuild(subList); // 子数据递归
212                 }else if(fields[j].getType() == Set.class){ // 如果属性是Set类型的
213                     Set<?> subSet = (Set<?>)value;
214                     Iterator<?> iter = subSet.iterator();
215                     List<Object> subList = new ArrayList<Object>(); 
216                     while(iter.hasNext()){
217                         subList.add(iter.next());
218                     }
219                     jsonSubBuild(subList); // 子数据递归
220                 }
221                 // 如果ClassLoader不是null表示该类不是启动类加载器加载的,不是Java API的类,是自己写的java类
222                 else if(null != fields[j].getType().getClassLoader()){ 
223                     jsonSubSubBuild(value, null); // 子子数据递归
224                 }
225                 else{ // 其它类型都认为是普通文本类型
226                     // 添加子元素(类属性)标签
227                     if(value.getClass() == String.class){
228                         result.append("'" + value + "'");
229                     }else{
230                         result.append(value.toString());
231                     }
232                     
233                 }
234                 
235                 //*********************************************************
236             } catch (Exception e) {
237                 e.printStackTrace();
238             }
239             
240         }
241         result.append("}");
242     }
243     
244     /**
245      * <ol>通过属性Field对象来获取getter方法的方法名。<br>
246      * 如果是boolean或Boolean类型(正则表达式来判断):isBorrow-->isBorrow();isborrow-->isIsborrow();<br>
247      * 否则:borrow-->getBorrow();
248      * </ol>
249      * @author wangjie
250      * @param field 要生成getter方法的对应属性对象。
251      * @return 返回getter方法的方法名。
252      */
253     private String getGetterMethodNameByFieldName(Field field){
254         String methodName = null;
255         String fieldName = field.getName();
256         // 解析属性对应的getter方法名
257         // 判断是否是boolean或Boolean类型:isBorrow-->isBorrow();isborrow-->isIsborrow()
258         if(field.getType() == boolean.class || field.getType() == Boolean.class){
259             if(fieldName.matches("^is[A-Z].*")){
260                 methodName = fieldName;
261             }else{
262                 methodName = "is" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
263             }
264         }else{
265             methodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
266         }
267         return methodName;
268     }
269     
270     /**
271      * 检验传入的List的合法性(List是不是为null、长度是不是为0、是不是每项都是同一个类型)
272      * @author wangjie
273      * @throws Exception 如果List为null, 或者长度为, 或者每项不是同一个类型, 抛出异常
274      */
275     private void checkValidityList() throws Exception{
276         if(null == list){
277             throw new Exception("请保证传入的List不为null");
278         }
279         int size = list.size();
280         if(list.size() == 0){
281             throw new Exception("请保证传入的List长度不为0");
282         }
283         for(int i = 1; i < size; i++){
284             if(list.get(0).getClass() != list.get(i).getClass()){
285                 throw new Exception("请保证传入的List每项都是同一个类型");
286             }
287         }
288         
289     }
290     
291     
292     
293 }

 

使用方法如下:

例如:
Student类(该类有属性name,age,isBoy,books等属性;其中books属性是一个List,存放Book对象):

1 private String name;
2 private int age;
3 private boolean isBoy;
4 private List<Book> books;
5 //并实现getter和setter方法;

 

Book类(该类有属性name,author,number,length,width,isBorrowed等属性):

1 private String name;
2 private String author;
3 private int number;
4 private float length;
5 private float width;
6 private boolean isBorrowed;
7 //并实现getter和setter方法;

 

现在有一个List<Student>类型的数据,通过以下代码把该List转换为Json:

List<Student> list = new ArrayList<Student>();//构建几个Student对象,放入list中
//……//完整数据版(不使用includes和excludes)
JOJSONBuilder jsonBuilder = new JOJSONBuilder(list);
String content = jsonBuilder.jsonBuild().toString();//或者使用包括/排除:
JOJSONBuilder jsonBuilder = new JOJSONBuilder(list, new String[]{"name", "age"}, null);
jsonBuilder.jsonBuild().toString();//或者使用方法链风格:
new JOJSONBuilder().setExcludes("name", "age").jsonBuild().toString();

 

转换之后的Json(完整数据版(不使用includes和excludes)):

 1 [
 2         {
 3                 'name':'hello',
 4                 'age':23,
 5                 'isBoy':true,
 6                 'books':[
 7                                         {
 8                                                 'name':'book1',
 9                                                 'author':'author1',
10                                                 'number':123,
11                                                 'length':23.5,
12                                                 'width':18.0,
13                                                 'isBorrowed':true
14                                         },
15                                         {
16                                                 'name':'book2',
17                                                 'author':'author2',
18                                                 'number':43,
19                                                 'length':42.23,
20                                                 'width':30.57,
21                                                 'isBorrowed':false
22                                         }
23                                 ]
24         },
25 
26         {
27                 'name':'world',
28                 'age':22,
29                 'isBoy':false,
30                 'books':[
31                                         {
32                                                 'name':'book1',
33                                                 'author':'author1',
34                                                 'number':123,
35                                                 'length':23.5,
36                                                 'width':18.0,
37                                                 'isBorrowed':true
38                                         },
39                                         {
40                                                 'name':'book3',
41                                                 'author':'author3',
42                                                 'number':875,
43                                                 'length':20.59,
44                                                 'width':15.08,
45                                                 'isBorrowed':false
46                                         },
47                                         {
48                                                 'name':'book4',
49                                                 'author':'author4',
50                                                 'number':165,
51                                                 'length':22.75,
52                                                 'width':19.61,
53                                                 'isBorrowed':true
54                                         }
55                                 ]
56         }
57 ]

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/266406.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql long类型_怒肝两个月MySQL源码,我总结出这篇2W字的MySQL协议详解(超硬核干货)!!...

点击上方蓝色“冰河技术”&#xff0c;关注并选择“设为星标”持之以恒&#xff0c;贵在坚持&#xff0c;每天进步一点点&#xff01;作者个人研发的在高并发场景下&#xff0c;提供的简单、稳定、可扩展的延迟消息队列框架&#xff0c;具有精准的定时任务和延迟队列处理功能。…

状压dp之二之三 炮兵阵地/玉米田 By cellur925

一、简单的状压dp 玉米田 题目描述 Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yummy corn for the cows on a number of squares. Regrettably, some of the squares…

LockSupport的源码实现原理以及应用

一、为什么使用LockSupport类 如果只是LockSupport在使用起来比Object的wait/notify简单&#xff0c; 那还真没必要专门讲解下LockSupport。最主要的是灵活性。 上边的例子代码中&#xff0c;主线程调用了Thread.sleep(1000)方法来等待线程A计算完成进入wait状态。如果去掉Thr…

python3 爬虫 requests安装_BOSS直聘招聘信息获取之爬虫工具分析

点击蓝色“不太灵光的程序员”关注我哟加个“星标”&#xff0c;每天上午 09:30&#xff0c;干货推送&#xff01;文中使用的组件库仅限于Python语言&#xff0c;由于最近收到一些同学的留言说&#xff0c;按照网上的教程一步一步的学习&#xff0c;却频繁的出现报错&#xff0…

假期周进度总计(四)

本周学习利用OEM工具创建删除表以及对表内数据进行增删改查的操作 一切均通过此工具进行&#xff0c;然后还学到了用SQL *Plus进行相应操作 本周每天4.5个小时&#xff0c;出现的错误就是点击的误操作&#xff0c;可以改正&#xff0c;下周进一步学习Oracle基本操作转载于:http…

Java集合框架(3)

Map(和Collection<E>一样都是集合框架的顶层接口) |--Hashtable:底层是哈希表数据结构&#xff0c;不可以用null对象作为键或值。它是线程同步的。 |--HashMap&#xff1a;底层是哈希表。允许使用null键null值&#xff0c;该集合是不同步的&#xff0c;效率高&#xff0c…

php函数从数组中取出指定的数目,PHP数组函数

1.array_rand()从数组中随机取出一个或多个元素(返回值是&#xff1a;随机元素的键)$arr[js,css,25,php,30];printf(%s,print_r($arr,true));//随机去2个元素$resarray_rand($arr,2);printf(%s,print_r($res,true));2.array_replace()使用后面数组元素相同 key 的值替换 array1…

存储过程 not supported yet_让我们来看看+Redis如何存储和计算一亿用户的活跃度

1前段时间&#xff0c;在网上看到一道面试题&#xff1a;如何用redis存储统计1亿用户一年的登陆情况&#xff0c;并快速检索任意时间窗口内的活跃用户数量。觉得很有意思&#xff0c;就仔细想了下 。并做了一系列实验&#xff0c;自己模拟了下 。还是有点收获的&#xff0c;现整…

HBase查询优化

1.概述 HBase是一个实时的非关系型数据库&#xff0c;用来存储海量数据。但是&#xff0c;在实际使用场景中&#xff0c;在使用HBase API查询HBase中的数据时&#xff0c;有时会发现数据查询会很慢。本篇博客将从客户端优化和服务端优化两个方面来介绍&#xff0c;如何提高查询…

NEC SV8100电话交换机配置梓博电话计费系统

为了节约办公成本&#xff0c;规范电话使用。公司最近为NEC SV8100电话交换机系统上线了一套梓博的电话计费系统。先将配置过程分享给各位。 1、登录电话交换机系统&#xff08;默认用户名tech、密码12345678&#xff09; 2、点击系统数据配置按钮 2、通过10-01选项调整电话交换…

判断闰年 php,PHP怎么判断一年是否为闰年?

判断是否为闰年的条件是满足下列二者条件之一&#xff1a;年号能被4整除、但不能被100整除&#xff0c;二是年号能被4整除&#xff0c;又能被400整除。那么PHP怎么判断一年是否为闰年&#xff1f;下面本篇文章就来给大家介绍一下使用PHP判断一年是否为闰年的方法&#xff0c;希…

redis desktop manager_面试官:Redis分布式锁如何解决锁超时问题?

Java面试笔试面经、Java技术每天学习一点Java面试关注不迷路作者&#xff1a;wangzaiplus来源&#xff1a;https://www.jianshu.com/u/8cb4591440ca一、前言关于redis分布式锁, 查了很多资料, 发现很多只是实现了最基础的功能, 但是, 并没有解决当锁已超时而业务逻辑还未执行完…

python print 换行_Python学习 | Python的基础语法

Python 语言与 Perl&#xff0c;C 和 Java 等语言有许多相似之处。但是&#xff0c;也存在一些差异&#xff0c;编写Paython程序之前需要对语法有所了解&#xff0c;才能编写规范的Python程序。一、行和缩进Python最大的特点之一就是Python 的代码块不使用大括号 {}了&#xff…

python 创建文件_Python入学首次项目,新手必看,简单易操作

继昨天文章python软件pycharm安装教程之后&#xff0c;今天则给新手小白们分享一哈&#xff0c;怎么制作并创建文件。print “hello world”&#xff1b;如后期需要资料文件的则可以私信留言&#xff0c;领取首次项目资料。本节知识点&#xff1a;python项目的创建pycharm的使用…

ajax跨域实现

2019独角兽企业重金招聘Python工程师标准>>> 我们都知道ajax是不能跨域的&#xff0c;那么怎么实现ajax跨域呢&#xff1f; 看了看jquery&#xff0c;当然&#xff0c;jquery封装的很好&#xff0c;$.ajax就可以实现跨域&#xff0c;只需要在参数中配置一下即可&am…

python leetcode_leetcode 刷题经验,主力 python

1. 树的先序遍历可以求高度&#xff0c;后序遍历可以求深度。剑指 Offer 55 - II. 平衡二叉树​leetcode-cn.com2. 二叉搜索树的中序遍历可以递增地返回所有元素。逆序的中序遍历&#xff08;即先右子节点&#xff0c;再根节点&#xff0c;再左子节点&#xff09;可以递减的返回…

sqlldr 导入乱码,Oracle客户端字符集问题

2019独角兽企业重金招聘Python工程师标准>>> 1&#xff0c;查Oracle数据库创建时候的字符集&#xff1a; Oracle服务器端执行 SQL> select name, value$ from sys.props$ where name like NLS%; NAME VALUE$ ------------------------------ -------------------…

Python在mysql中进行操作是十分容易和简洁的

首先声明一下&#xff0c;我用的是Windows系统&#xff01; 1、在Python中对mysql数据库进行操作首先要导入pymysql模块&#xff0c;默认情况下&#xff0c;Python中是没有安装这个模块的&#xff0c; 可以在Windows的命令行中用pip install pymysql来安装&#xff08;注意要连…

讲php fpm的书,细说PHP-fpm

最近在研究PHP的源码&#xff0c;有时候会延伸到很多东西。这里就专程找了下php-fpm的内容学习下。是什么&#xff1f;在理解php-fpm之前&#xff0c;我们要先搞清楚几个关键词以及他们之间的关系:CGIFastCGIphp-fpmphp-cgi.CGI:(Common Gateway Interface)&#xff0c;即通用网…

安卓微软雅黑字体ttf_618巨献丨精致的悦黑5字重小字体

悦黑字体简介去年双十一当天&#xff0c;小编应大家要求&#xff0c;分享了一款悦黑小字体&#xff0c;苹果和安卓都有&#xff1a;双十一巨献&#xff1a;令人瑟瑟发抖的5字重悦黑小字体大半年时间过去了&#xff0c;一直没有更新&#xff0c;今天抽空更新一下。悦黑是由造字工…