- 浏览: 344517 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (249)
- 无废话ExtJs 系列教程 (26)
- jQuery (6)
- 钦波工作后的生活 (5)
- 工作/生活闲谈 (16)
- java基础知识 (44)
- java web (14)
- Struts (1)
- hibernate (8)
- Jpa (0)
- spring (1)
- ajax (3)
- java项目 (4)
- database (5)
- java 流行框架 (5)
- 异常处理 (4)
- 无废话Android系统教程 (6)
- 开发IDE (1)
- 亲自答过的java笔试题 (2)
- oa项目 (4)
- [ 民政局3.0系统 ]--知识点总结分析--与具体项目无关 (0)
- [ 黑龙江低保系统 ]--知识点总结分析--与具体项目无关 (2)
- 工作笔试 (1)
- xml (1)
- telecom项目分析 (13)
- swing (0)
- String运用 (2)
- css (1)
- 页面 (1)
- Html5 (2)
- oracle (4)
- 网站 (1)
- django (1)
- python (4)
- 民航数据中心遇到与解决的问题 (1)
- 平时关注的技术或特效 (1)
- Linux 命令 (2)
- 服务器监控工具 (1)
最新评论
-
wwytwen123:
[*]
java类中静态域、块,非静态域、块,构造函数的初始化顺序(回钦波) -
junying280efun:
yingtao.huang@gmail.com仁兄,麻烦你给我 ...
jBPM Web Designer(jBPM Web 设计器、jBPM 流程设计器、工作流程设计器) -
mobeicanglang:
我觉得楼主的例子全部都有错误,题目明明说的是try{}语句中有 ...
try return finally -
ashy1q:
楼主最后那段代码重复了,写了两遍。知识很详细,很基础,学习了。 ...
java类中静态域、块,非静态域、块,构造函数的初始化顺序(回钦波) -
185552143:
你好!
为什么我这样写p${m.id},会报错的?
能我帮我解 ...
Session问题
简介:
本文介绍使用 Json-lib 将 JavaBean 转换为 JSON 数据的方法。我们将使用 annotation 来灵巧地筛选 JavaBean 中的属性,并通过 annotation 来定义特殊的 JsonValueProcessor。
如 今大量的 Web 站点应用了 AJAX 技术,通过更少的数据通讯,服务器能够更快的反馈用户请求,再通过 Javascript 的控制,让使用者有了更好的用户体验。JSON 是一种轻量级的数据交换语言,它是 Javascript 的一个子集,又有良好的可读性,经常用于客户端和服务器间的数据交换。因此,在服务器端,常常需要将实体对象(JavaBean)转换为 JSON 格式数据。本文介绍了如何使用 Json-lib 转换 JavaBean 为 JSON 格式数据,并给出解决方法,以及利用 annotation 来增强 Json-lib 的两个功能:一是灵活的筛选 JavaBean 属性;二是通过 JsonValueProcessor 来自定义如何转换 JavaBean 属性到 JSON 数据。
JSON 的数据格式简单易读,它存在于两种基本形式:
- 名值对(Collection):名称与值用‘:’分开;名值对之间用‘,’分隔;整体用‘ {} '括起来。例如 {name1:value1, name2:value2}
- 值的有序队列(Array):即数组,每个值之间用‘,’分隔;整体用‘ [] '括起来。例如:[value1, value2]
这两种形式的有机组合,就形成了 JSON 数据。
使用 Json-lib 转换 JavaBean 为 JSON 数据
Json-lib 是一个 java 工具库,它提供 api 来转换 JavaBean,Map,Collection 等对象为 JSON 数据,或反过来通过 JSON 数据得到 JavaBean。
Json-lib 的使用很容易,只要使用 JSONSerializer 的 toJSON 方法就可以转换任意的 Java Object 为 JSON 对象了,再调用 JSON 对象的 toString 方法可以得到转换后的字符串。不过还有一些进一步的问题需要我们自己来解决。
import net.sf.json.JSONSerializer;
List list = new ArrayList();
list.add( "first" );
list.add( "second" );
JSON json = JSONSerializer.toJSON( list );
System.out.println( json.toString() );
// prints ["first","second"]
class MyBean{
private String name = "json";
private int pojoId = 1;
// getters & setters
...
}
json = JSONSerializer.toJSON( new MyBean() );
System.out.println( json.toString() );
// prints {"name":"json","pojoId":1}
|
清单 1 中的例子转换后的 JSON 数据中包含了 JavaBean 中的全部属性,可是我们常常需要有选择的提取 JavaBean 中的特定属性出来。例如:
- 需要过滤掉循环引用的属性,这一点 json-lib 提供了 CycleDetectionStrategy 来处理,但是直接过滤掉更简单;
- 不同的情况下只需要 JavaBean 中的部分属性:比如列表界面只需要显示 Bean 的几个重要属性,而详情界面则需要显示更多的 Bean 的属性;
- 不同的用户权限限制用户只能获得某些属性数据;
对于普通的 Object 类型(如 Long,String 等),json-lib 有缺省的值转换处理方式,但是对于一些特殊的类型,我们希望用自定义的方式来转换该属性的值。例如:
- 对于 java.util.Date 类型,我们希望直接转换成时间串:2010-04-10,而不希望得到一个类似 {"year":"2010","month":"4","day":"10"} 这样的结果
- 对于常用到的代码数据(比如:性别),在定义时它也许是个 Integer(男:1;女:2),我们希望在转换后直接得到:{"性别":"男",...},而不是 {"性别":"1",...}
Json-lib 已经预留出一些接口,让用户修改它的缺省行为。下面我们来看看如何利用 annotation 来配合 Json-lib 解决这两个问题。
JSONSerializer 提供了一个 toJSON 的重载方法,增加一个参数 JsonConfig,可以通过这个参数对 Json-lib 的缺省方式做自定义的配置。
清单 2. 自定义 JSONSerializer 的属性过滤器
import net.sf.json.JSONSerializer; import net.sf.json.JsonConfig; import net.sf.json.util.PropertyFilter; // 定义属性过滤器 PropertyFilter filter = new PropertyFilter( public boolean apply(Object source, String name, Object value) { if ( name.equals( “pojoId” ) ) { return true; // 返回 true, 表示这个属性将被过滤掉 } return false; } ); // 注册属性过滤器 JsonConfig config = new JsonConfig(); config.setJsonPropertyFilter( filter ); System.out.println( JSONSerializer.toJSON( new MyBean(), config ) ); // prints {"name":"json"} |
从 清单 2 中可以看出来,Json-lib 通过 PropertyFilter 的 apply 方法进行属性过滤,可以象例子中一样,把所有需要过滤的属性名称写进去,但是这样做太烦琐,也不好维护,对不同的 Bean 要做不同的处理。下面让我们看看怎么利用 annotation 来更方便的处理。
首先,需要定义一个 annotation,并给 MyBean 的 get 方法加上标注。
清单 3. 定义一个 annotation: Invisible
import java.lang.annotation.Target; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.ElementType; import java.lang.annotation.RetentionPolicy; @Documented @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Invisible { public String[] value(); } // 为myBean中需要过滤的属性get方法(或者is方法)加上Invisible标注 public class MyBean{ private String name = "json"; private int pojoId = 1; // getters & setters public String getName() { return name; } @Invisible(“LIST”) // 在 “LIST” 情况下不要这个属性 public int getPojoId() { return pojoId; } } |
然后,我们需要一些能处理 annotation 的 PropertyFilter 类。
清单 4. 处理 annotation 的 PropertyFilter 类
import java.util.Map; import java.lang.reflect.Method; import net.sf.json.util.PropertyFilter; // 先实现一个abstract类,将读取Bean属性的Method找到并传递给子类处理 public abstract class AbstractMethodFilter implements PropertyFilter { // 这个方法留给子类实现,以便适应不同的过滤需求 public abstract boolean apply(final Method method); public boolean apply(final Object source, final String name, final Object value) { if (source instanceof Map) { return false; } String propName = name.substring(0, 1).toUpperCase() + name.substring(1); Class clz = source.getClass(); String methodName = "get" + propName; Method method = null; try { method = clz.getMethod(methodName, (Class[]) null); // 寻找属性的get方法 } catch (NoSuchMethodException nsme) { String methodName2 = "is" + propName; // 也许是个is方法 try { method = clz.getMethod(methodName2, (Class[]) null); } catch (NoSuchMethodException ne) { // 没有找到属性的get或者is方法,打印错误,返回true System.err.println(“No such methods: ” + methodName + “ or “ + methodName2); return true; } } return apply(method); } } // END: AbstractMethodFilter public class InvisibleFilter extends AbstractMethodFilter { // 过滤条件,标注中有符合这个条件的property将被过滤掉 private String _sGUIID; public InvisibleFilter(final String guiid) { _sGUIID = guiid; } public boolean apply(final Method method) { if (_sGUIID == null || _sGUIID.equals(“”)) { return false; // 表示不做限制 } if (method.isAnnotationPresent(Invisible.class)) { Invisible anno = method.getAnnotation(Invisible.class); String[] value = anno.value(); for (int i = 0; i < value.length; i++) { if (_sGUIID.equals(value[i])) { return true; } } } return false; } } |
现在只要把这个 filter 注册到 JsonConfig 中,就实现了属性的过滤,请看清单 5。
清单 5. 使用 InvisibleFilter 来过滤不需要的属性
JsonConfig config = new JsonConfig(); config.setJsonPropertyFilter( new InvisibleFilter(“LIST”)); //标注了LIST的属性将被过滤掉 System.out.println( JSONSerializer.toJSON( new MyBean(), config ) ); // prints {"name":"json"} |
增加其他的 annotation 及 Filter 就可以实现不同的属性过滤方式了。
使用 annotation 自定义 Bean 属性的转换方式
Json-lib 通过 JsonConfig 提供了自定义属性转换方式的接口。
JsonConfig config = new JsonConfig(); config.registerJsonValueProcessor(java.util.Date.class, new JsDateJsonValueProcessor()); |
注册后 Json-lib 在遇到 java.uitl.Date 类型的属性时,会应用 JsDateJsonValueProcessor 的处理方法。
所以,只要实现自己的 JsonValueProcessor 就可以自定义各种 Object 的转换方式了。
根 据上一节的讨论,Json-lib 在转换 Bean 属性之前,会将属性数据传递给 PropertyFilter 来判断是否需要过滤掉。因此,我们可以通过一个 Filter 对象获得 Bean 的属性的标注数据,并将它传递给特定的 Processor,Processor 根据得到的标注值知道应该怎么处理这个属性。下面以整型代码为例,说明处理的方法。
一般情况下,一个项目中会涉及许多种不同的代码,我们会为每一种代码定义一个主代码号(代码往往都是整型的),为它的子项定义几个子代码号。例如,我们定义性别的主代码号为 100,并定义男:1,女:2。
首先,需要一个代码标注(IntegerCode)及一个处理这种标注的 PropertyFilter。
清单 7. IntegerCode 及 IntegerCodeFilter
@Documented @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface IntegerCode { public int value(); } public class IntegerCodeFilter extends AbstractMethodFilter { // 代码处理器 private IntegerCodeProcessor _processor; public IntegerCodeFilter(final IntegerCodeProcessor processor) { _processor = processor; } // 不过滤属性,但当发现IntegerCode标注时,将数据传递给Processor public boolean apply(final Method method) { if (_processor == null) { return false; // 表示没有特别的处理 } if (method.isAnnotationPresent(IntegerCode.class)) { IntegerCode anno = method.getAnnotation(IntegerCode.class); int code = anno.value(); _processor.setMainCode(code); // 将code设置为主代码 } return false; } } |
现在,我们需要一个 JsonValueProcessor 来处理 IntegerCode 数据。
public class IntegerCodeProcessor implements JsonValueProcessor { private int _iMainCode; public void setMainCode(final int mainCode) { _iMainCode = mainCode; } public IntegerCodeProcessor() { super(); } // END: IntegerCodeProcessor private void reset() { _iMainCode = -1; } public Object processArrayValue(Object value, JsonConfig jsonConfig) { return process(value, jsonConfig); } // END: processArrayValue public Object processObjectValue( String key, Object value, JsonConfig jsonConfig ) { return process( value, jsonConfig ); } // END: processObjectValue private Object process(Object value, JsonConfig jsonConfig) { if (value == null) { return null; } String ret = null; if (value instanceof Integer && _iMainCode >= 0) { int code = value.intValue(); switch (_iMainCode) { case 100: // 这里使用简单的case 处理不同的代码 if (code == 1) { // 好一点的方式是从资源文件中读取对应值 ret = "man"; } else if (code == 2) { ret = "woman"; } else { ret = value.toString(); } break; default: ret = value.toString(); break; } } else { ret = value.toString(); } reset(); // 处理后重置,以免影响其他 Integer 属性 return ret; } // END: process } |
现在,我们创建一个 JavaBean:Student 来测试这个 Processor。
public class Student { private String name = "camry"; private int gender = 1; // getters & setters public String getName() { return name; } @IntegerCode(100) // 性别主代码为 100 public int getGender() { return gender; }} } ... IntegerCodeProcessor processor = new IntegerCodeProcessor(); IntegerCodeFilter filter = new IntegerCodeFilter(processor); JsonConfig config = new JsonConfig(); config.setJsonPropertyFilter( filter ); config.registerJsonValueProcessor(Integer.class, processor); System.out.println( JSONSerializer.toJSON( new Student(), config ) ); // prints {“gender”:”man”, "name":"camry"} |
Json-lib 可以很方便的进行 JavaBean 到 JSON 数据的转换,再结合 annotation 为 JavaBean 的属性定义元数据,可以减少代码,提高效率。
学习
- “JSON 入门指南
”(developerWorks,2008 年 8 月):本文将快速讲解 JSON 格式,并通过代码示例演示如何分别在客户端和服务器端进行 JSON 格式数据的处理。
- “掌握 Ajax,第 10 部分: 使用 JSON 进行数据传输
”(developerWorks,2007 年 4 月):讨论另一种有用的数据格式 JSON,以及如何使用它更轻松地在应用程序中移动数据和对象。
- 参考 JSON
主页,了解 JSON 数据格式的详细说明。
- 参考“Json-lib 主页
”,了解 Json-lib 的实现与使用。
- 参考“Java 站点
”,了解更多关于 annotation 的知识。
发表评论
-
JavaBean到XML和JSON的转换 附件中有xtream.1.3.1.jar包
2011-11-21 15:14 1527XML和JSON是当今常用的两种数据描述与传输的格式,特别是涉 ... -
JSON-lib框架,转换JSON、XML不再困难【回钦波】
2011-11-16 19:19 1192JSON-lib框架,转换JSON、XML不再困难 ... -
JAXB2完成java bean到xml的相互转换【转】
2011-11-11 11:09 1350JAXB2完成java bean到xml的相互转换 ... -
JSON与XML内容间的区别
2011-11-09 19:52 1350JSON <script type="t ... -
jdk log日志输出经典实例【回钦波】
2011-09-07 17:29 1804Logger所对应的属性文件在安装jdk目录下的jre/lib ... -
Java 日志记录 log4j 最简明教程
2011-09-06 13:57 1740最近在搞一个项目架设,希望从构建一个项目方方面面都彻底研究透 ... -
Log日[huiqinbo查看]
2011-09-05 23:10 906Log日志 log4jHibernate配置管理JD ... -
一个简单的css+div布局实例,让你很明了的了解怎么布局!
2010-07-07 16:21 2644一个简单的css+div布局实例,让你很明了的了解怎么布局! ... -
玩转div定位
2010-07-07 14:42 1450玩转div定位 (2010-01-18 14:00:10 ... -
大型门户网站实现的十四大技术
2010-05-06 11:39 2148大型门户网站实现的十 ... -
jsp页面传到业务层时有时会出现乱码问题(钦波小小答疑)
2010-04-08 17:18 1045当前台jsp页面传到业务层时有时会出现乱码问题,这时不要急仔细 ... -
自定义JSTL标签函数,方便个人使用
2010-03-26 02:36 1626自定义JSTL标签函数,方便页面的调用,通过调用函数返回数据进 ... -
session的值处理
2010-03-26 01:14 840:*******只要是放到request,session,ap ...
相关推荐
2. **配置和扩展**:在 Spring 的配置文件中,可以定义自定义的 `HttpMessageConverter` 实现,以便在处理请求和响应时使用 JSON-lib 进行数据转换。这可以通过在 `<mvc:annotation-driven>` 或 `<bean>` 元素中配置...
在SpringMVC中,我们可以使用Jackson的`@ResponseBody`注解,将控制器方法的返回值自动转换为JSON格式。同时,通过`@RequestBody`注解,我们可以将HTTP请求体中的JSON数据自动映射到方法参数中。 配置Jackson库需要...
赠送jar包:javax.annotation-api-1.2.jar; 赠送原API文档:javax.annotation-api-1.2-javadoc.jar; 赠送源代码:javax.annotation-api-1.2-sources.jar; 赠送Maven依赖信息文件:javax.annotation-api-1.2.pom;...
赠送jar包:jakarta.annotation-api-1.3.5.jar; 赠送原API文档:jakarta.annotation-api-1.3.5-javadoc.jar; 赠送源代码:jakarta.annotation-api-1.3.5-sources.jar; 赠送Maven依赖信息文件:jakarta.annotation...
赠送jar包:jakarta.annotation-api-1.3.5.jar; 赠送原API文档:jakarta.annotation-api-1.3.5-javadoc.jar; 赠送源代码:jakarta.annotation-api-1.3.5-sources.jar; 赠送Maven依赖信息文件:jakarta.annotation...
赠送jar包:javax.annotation-api-1.3.2.jar; 赠送原API文档:javax.annotation-api-1.3.2-javadoc.jar; 赠送源代码:javax.annotation-api-1.3.2-sources.jar; 赠送Maven依赖信息文件:javax.annotation-api-...
在Java编程语言中,...通过深入理解和正确使用`javax.annotation-api-1.3.2.jar` 中提供的注解,开发者可以编写出更加简洁、可维护且易于扩展的代码,特别是在企业级Java应用开发中,注解的运用是不可或缺的一部分。
赠送jar包:javax.annotation-api-1.3.2.jar; 赠送原API文档:javax.annotation-api-1.3.2-javadoc.jar; 赠送源代码:javax.annotation-api-1.3.2-sources.jar; 包含翻译后的API文档:javax.annotation-api-...
JDK9及以上版本没有javax.annotation-api-***.jar包 ,无法使用注解:@Resource JDK新特性,高版本JDK没有自带的javax...下载javax.annotation.jar包,导入到lib文件夹下,然后Add as library,就可以使用@Resource
赠送jar包:javax.annotation-api-1.2.jar; 赠送原API文档:javax.annotation-api-1.2-javadoc.jar; 赠送源代码:javax.annotation-api-1.2-sources.jar; 赠送Maven依赖信息文件:javax.annotation-api-1.2.pom;...
javax.annotation-api-1.2.jar包,注解,声明,@Resource是做bean的注入使用。
赠送jar包:mybatis-plus-annotation-3.2.0.jar; 赠送原API文档:mybatis-plus-annotation-3.2.0-javadoc.jar; 赠送源代码:mybatis-plus-annotation-3.2.0-sources.jar; 赠送Maven依赖信息文件:mybatis-plus-...
@Resource注解所在的jar包 与@Autowired不同的是此注解是ByName进行依赖注入的
赠送jar包:mybatis-plus-annotation-3.5.1.jar; 赠送原API文档:mybatis-plus-annotation-3.5.1-javadoc.jar; 赠送源代码:mybatis-plus-annotation-3.5.1-sources.jar; 赠送Maven依赖信息文件:mybatis-plus-...
赠送jar包:mybatis-plus-annotation-3.1.0.jar; 赠送原API文档:mybatis-plus-annotation-3.1.0-javadoc.jar; 赠送源代码:mybatis-plus-annotation-3.1.0-sources.jar; 赠送Maven依赖信息文件:mybatis-plus-...
赠送jar包:mybatis-plus-annotation-3.5.1.jar; 赠送原API文档:mybatis-plus-annotation-3.5.1-javadoc.jar; 赠送源代码:mybatis-plus-annotation-3.5.1-sources.jar; 赠送Maven依赖信息文件:mybatis-plus-...
在实际使用中,`annotation-file-utilities.jar`可能需要与其他构建工具(如Maven或Gradle)配合,通过指定依赖关系将其引入项目。开发者可以利用这个库提供的功能,编写更加高效和可维护的代码,同时减少手动配置和...
赠送jar包:mybatis-plus-annotation-3.1.0.jar; 赠送原API文档:mybatis-plus-annotation-3.1.0-javadoc.jar; 赠送源代码:mybatis-plus-annotation-3.1.0-sources.jar; 赠送Maven依赖信息文件:mybatis-plus-...
在描述中提到的"mybatis-generator-core-chinese-annotation-1.3.5-master.zip"是一个包含MBG中文注解版1.3.5版本的压缩包,旨在帮助开发者更方便地理解和使用这个工具。 MBG的核心功能在于根据数据库表自动生成...
sentinel-annotation-aspectj-1.4.0.jar