一,setCycleDetectionStrategy 防止自包含

  1. /**
  2. * 这里测试如果含有自包含的时候需要CycleDetectionStrategy
  3. */
  4. public static void testCycleObject() {
  5. CycleObject object = new CycleObject();
  6. object.setMemberId("yajuntest");
  7. object.setSex("male");
  8. JsonConfig jsonConfig = new JsonConfig();
  9. jsonConfig.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);
  10. JSONObject json = JSONObject.fromObject(object, jsonConfig);
  11. System.out.println(json);
  12. }
  13. public static void main(String[] args) {
  14. JsonTest.testCycleObject();
  15. }

其中 CycleObject.java是我自己写的一个类:

  1. public class CycleObject {
  2. private String      memberId;
  3. private String      sex;
  4. private CycleObject me = this;
  5. …… // getters && setters
  6. }

输出 {"sex":"male","memberId":"yajuntest","me":null}

二,setExcludes:排除需要序列化成json的属性

  1. public static void testExcludeProperites() {
  2. String str = "{'string':'JSON', 'integer': 1, 'double': 2.0, 'boolean': true}";
  3. JsonConfig jsonConfig = new JsonConfig();
  4. jsonConfig.setExcludes(new String[] { "double", "boolean" });
  5. JSONObject jsonObject = (JSONObject) JSONSerializer.toJSON(str, jsonConfig);
  6. System.out.println(jsonObject.getString("string"));
  7. System.out.println(jsonObject.getInt("integer"));
  8. System.out.println(jsonObject.has("double"));
  9. System.out.println(jsonObject.has("boolean"));
  10. }
  11. public static void main(String[] args) {
  12. JsonTest.testExcludeProperites();
  13. }

三,setIgnoreDefaultExcludes

  1. @SuppressWarnings("unchecked")
  2. public static void testMap() {
  3. Map map = new HashMap();
  4. map.put("name", "json");
  5. map.put("class", "ddd");
  6. JsonConfig config = new JsonConfig();
  7. config.setIgnoreDefaultExcludes(true);  //默认为false,即过滤默认的key
  8. JSONObject jsonObject = JSONObject.fromObject(map,config);
  9. System.out.println(jsonObject);
  10. }

上面的代码会把name 和 class都输出。

而去掉setIgnoreDefaultExcludes(true)的话,就只会输出name,不会输出class。

  1. private static final String[] DEFAULT_EXCLUDES = new String[] { "class", "declaringClass",
  2. "metaClass" }; // 默认会过滤的几个key

四,registerJsonBeanProcessor 当value类型是从java的一个bean转化过来的时候,可以提供自定义处理器

  1. public static void testMap() {
  2. Map map = new HashMap();
  3. map.put("name", "json");
  4. map.put("class", "ddd");
  5. map.put("date", new Date());
  6. JsonConfig config = new JsonConfig();
  7. config.setIgnoreDefaultExcludes(false);
  8. config.registerJsonBeanProcessor(Date.class,
  9. new JsDateJsonBeanProcessor()); // 当输出时间格式时,采用和JS兼容的格式输出
  10. JSONObject jsonObject = JSONObject.fromObject(map, config);
  11. System.out.println(jsonObject);
  12. }

注:JsDateJsonBeanProcessor 是json-lib已经提供的类,我们也可以实现自己的JsonBeanProcessor。

五,registerJsonValueProcessor

六,registerDefaultValueProcessor

为了演示,首先我自己实现了两个 Processor

一个针对Integer

  1. public class MyDefaultIntegerValueProcessor implements DefaultValueProcessor {
  2. public Object getDefaultValue(Class type) {
  3. if (type != null && Integer.class.isAssignableFrom(type)) {
  4. return Integer.valueOf(9999);
  5. }
  6. return JSONNull.getInstance();
  7. }
  8. }

一个针对PlainObject(我自定义的类)

  1. public class MyPlainObjectProcessor implements DefaultValueProcessor {
  2. public Object getDefaultValue(Class type) {
  3. if (type != null && PlainObject.class.isAssignableFrom(type)) {
  4. return "美女" + "瑶瑶";
  5. }
  6. return JSONNull.getInstance();
  7. }
  8. }

以上两个类用于处理当value为null的时候该如何输出。

还准备了两个普通的自定义bean

PlainObjectHolder:

  1. public class PlainObjectHolder {
  2. private PlainObject object; // 自定义类型
  3. private Integer a; // JDK自带的类型
  4. public PlainObject getObject() {
  5. return object;
  6. }
  7. public void setObject(PlainObject object) {
  8. this.object = object;
  9. }
  10. public Integer getA() {
  11. return a;
  12. }
  13. public void setA(Integer a) {
  14. this.a = a;
  15. }
  16. }

PlainObject 也是我自己定义的类

  1. public class PlainObject {
  2. private String memberId;
  3. private String sex;
  4. public String getMemberId() {
  5. return memberId;
  6. }
  7. public void setMemberId(String memberId) {
  8. this.memberId = memberId;
  9. }
  10. public String getSex() {
  11. return sex;
  12. }
  13. public void setSex(String sex) {
  14. this.sex = sex;
  15. }
  16. }

A,如果JSONObject.fromObject(null) 这个参数直接传null进去,json-lib会怎么处理:

  1. public static JSONObject fromObject( Object object, JsonConfig jsonConfig ) {
  2. if( object == null || JSONUtils.isNull( object ) ){
  3. return new JSONObject( true );

看代码是直接返回了一个空的JSONObject,没有用到任何默认值输出。

B,其次,我们看如果java对象直接是一个JDK中已经有的类(什么指 Enum,Annotation,JSONObject,DynaBean,JSONTokener,JSONString,Map,String,Number,Array),但是值为null ,json-lib如何处理

JSONObject.java

  1. }else if( object instanceof Enum ){
  2. throw new JSONException( "'object' is an Enum. Use JSONArray instead" ); // 不支持枚举
  3. }else if( object instanceof Annotation || (object != null && object.getClass()
  4. .isAnnotation()) ){
  5. throw new JSONException( "'object' is an Annotation." ); // 不支持 注解
  6. }else if( object instanceof JSONObject ){
  7. return _fromJSONObject( (JSONObject) object, jsonConfig );
  8. }else if( object instanceof DynaBean ){
  9. return _fromDynaBean( (DynaBean) object, jsonConfig );
  10. }else if( object instanceof JSONTokener ){
  11. return _fromJSONTokener( (JSONTokener) object, jsonConfig );
  12. }else if( object instanceof JSONString ){
  13. return _fromJSONString( (JSONString) object, jsonConfig );
  14. }else if( object instanceof Map ){
  15. return _fromMap( (Map) object, jsonConfig );
  16. }else if( object instanceof String ){
  17. return _fromString( (String) object, jsonConfig );
  18. }else if( JSONUtils.isNumber( object ) || JSONUtils.isBoolean( object )
  19. || JSONUtils.isString( object ) ){
  20. return new JSONObject();  // 不支持纯数字
  21. }else if( JSONUtils.isArray( object ) ){
  22. throw new JSONException( "'object' is an array. Use JSONArray instead" ); //不支持数组,需要用JSONArray替代
  23. }else{

根据以上代码,主要发现_fromMap是不支持使用DefaultValueProcessor 的。

原因看代码:

JSONObject.java

  1. if( value != null ){ //大的前提条件,value不为空
  2. JsonValueProcessor jsonValueProcessor = jsonConfig.findJsonValueProcessor(
  3. value.getClass(), key );
  4. if( jsonValueProcessor != null ){
  5. value = jsonValueProcessor.processObjectValue( key, value, jsonConfig );
  6. if( !JsonVerifier.isValidJsonValue( value ) ){
  7. throw new JSONException( "Value is not a valid JSON value. " + value );
  8. }
  9. }
  10. setValue( jsonObject, key, value, value.getClass(), jsonConfig );
  1. private static void setValue( JSONObject jsonObject, String key, Object value, Class type,
  2. JsonConfig jsonConfig ) {
  3. boolean accumulated = false;
  4. if( value == null ){ // 当 value为空的时候使用DefaultValueProcessor
  5. value = jsonConfig.findDefaultValueProcessor( type )
  6. .getDefaultValue( type );
  7. if( !JsonVerifier.isValidJsonValue( value ) ){
  8. throw new JSONException( "Value is not a valid JSON value. " + value );
  9. }
  10. }
  11. ……

根据我的注释, 上面的代码显然是存在矛盾。

_fromDynaBean是支持DefaultValueProcessor的和下面的C是一样的。

C,我们看如果 java 对象是自定义类型的,并且里面的属性包含空值(没赋值,默认是null)也就是上面B还没贴出来的最后一个else

  1. else {return _fromBean( object, jsonConfig );}

我写了个测试类:

  1. public static void testDefaultValueProcessor() {
  2. PlainObjectHolder holder = new PlainObjectHolder();
  3. JsonConfig config = new JsonConfig();
  4. config.registerDefaultValueProcessor(PlainObject.class,
  5. new MyPlainObjectProcessor());
  6. config.registerDefaultValueProcessor(Integer.class,
  7. new MyDefaultIntegerValueProcessor());
  8. JSONObject json = JSONObject.fromObject(holder, config);
  9. System.out.println(json);
  10. }

这种情况的输出值是 {"a":9999,"object":"美女瑶瑶"}
即两个Processor都起作用了。

========================== Json To Java ===============

一,ignoreDefaultExcludes

  1. public static void json2java() {
  2. String jsonString = "{'name':'hello','class':'ddd'}";
  3. JsonConfig config = new JsonConfig();
  4. config.setIgnoreDefaultExcludes(true); // 与JAVA To Json的时候一样,不设置class属性无法输出
  5. JSONObject json = (JSONObject) JSONSerializer.toJSON(jsonString,config);
  6. System.out.println(json);
  7. }

========================== JSON 输出的安全问题 ===============

我们做程序的时候主要是使用 Java To Json的方式,下面描述的是 安全性问题:

  1. @SuppressWarnings("unchecked")
  2. public static void testSecurity() {
  3. Map map = new HashMap();
  4. map.put("\"}<IMG src='x.jpg' onerror=javascript:alert('说了你不要进来') border=0> {", "");
  5. JSONObject jsonObject = JSONObject.fromObject(map);
  6. System.out.println(jsonObject);
  7. }
  1. public static void main(String[] args) {
  2. JsonTest.testSecurity();
  3. }

输出的内容:

{"\"}<IMG src='x.jpg' onerror=javascript:alert('说了你不要进来') border=0> {":"" }

如果把这段内容直接贴到记事本里面,命名为 testSecu.html ,然后用浏览器打开发现执行了其中的 js脚本。这样就容易产生XSS安全问题。

JSON lib 里JsonConfig详解的更多相关文章

  1. Jquery遍历筛选数组的几种方法和遍历解析json对象|Map()方法详解

    Jquery遍历筛选数组的几种方法和遍历解析json对象|Map()方法详解 一.Jquery遍历筛选数组 1.jquery grep()筛选遍历数组 $().ready( function(){ v ...

  2. 『动善时』JMeter基础 — 35、JMeter接口关联【JSON提取器】详解

    目录 1.JSON提取器介绍 2.JSON提取器界面详解 3.JSON提取器的使用 (1)测试计划内包含的元件 (2)HTTP Cookie管理器内容 (3)用户登陆请求界面内容 (4)JSON提取器 ...

  3. JSON Web Token 使用详解

    JWT 是什么? JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案.它是有三部分组成,示例如下,具体的讲解如下(jwt 是不会有空行的,下面只是为了显示,便使用了换行看着比较 ...

  4. JQuery解析HTML、JSON和XML实例详解

    1.HTML 有的时候会将一段HTML片段保存在HTML文件中,在另外的主页面直接读取该HTML文件,然后解析里面的HTML代码片段融入到主页面中. fragment.html文件,其内容: 复制代码 ...

  5. HttpURLConnection从网上获取Json数据并解析详解

    HttpURLConnection从网上获取Json数据并解析 1.HttpURLConnection请求数据的步骤 (1)构造一个URL接口地址: URL url = new URL("h ...

  6. python接口自动化(十九)--Json 数据处理---实战(详解)

    简介 上一篇说了关于json数据处理,是为了断言方便,这篇就带各位小伙伴实战一下.首先捋一下思路,然后根据思路一步一步的去实现和实战,不要一开始就盲目的动手和无头苍蝇一样到处乱撞,撞得头破血流后而放弃 ...

  7. python接口自动化(九)--python中字典和json的区别(详解)

    简介 这篇文章的由来是由于上一篇发送post请求的接口时候,参数传字典(dict)和json的缘故,因为python中,json和dict非常类似,都是key-value的形式,为啥还要这么传参,在群 ...

  8. Python全栈之路----常用模块----序列化(json&pickle&shelve)模块详解

    把内存数据转成字符,叫序列化:把字符转成内存数据类型,叫反序列化. Json模块 Json模块提供了四个功能:序列化:dumps.dump:反序列化:loads.load. import json d ...

  9. C# XML与Json之间相互转换实例详解

    对于这转换其实很简单,其中最重要的就是先要引用类库.可以到官网进行下载引用http://json.codeplex.com. XML转换为Json字符串 string xml = @"< ...

随机推荐

  1. hdu-4471-Homework-矩阵快速幂+优化加速

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4471 题目意思: 求f(n). 当n为特殊点nk时 解题思路: 当x不为特殊点时,直接用基本的矩阵快 ...

  2. sqlserver2000 数据库分页查询[根据网上搜索到得sql修改,亲测,可用]

    SELECT TOP 页大小 * FROM TestTable WHERE (ID > (SELECT case when count(0) < 页大小 then 0 else MAX(i ...

  3. 横瓜从WP7与WP8不兼容之处预测微软公司在未来20年将会倒闭

    横瓜(601069289)  12:40:50 微软频繁升级操作系统版本捞钱,还不向下兼容,其企业的核心竞争力不再是技术,是钱!除了操作系统,其它产品没有任何核心技术和竞争力,微软必死. 横瓜从WP7 ...

  4. Data Guard组件等相关介绍

    1.Data Guard组件介绍  Data Guard架构归类为3个主要的组件. Data Guard 重做传输服务  重做传输服务用来将主数据库生成的重做数据传输给备用数据库. Data Guar ...

  5. 个人知识管理利器wiz

    Personal Knowledge Management PKM(Personal Knowledge Management),中文译为个人知识管理. 个人知识管理是一种新的知识管理的理念和方法,能 ...

  6. 使用 EasyUI 创建左侧导航菜单

    使用 JQuery EasyUI 创建左侧导航菜单,菜单的数据由后台服务提供. 效果图 HTML 元素 <div id="menuAccordion"></div ...

  7. Springmvc中配置Quartz使用,实现任务实时调度。

    菜鸡的自我修炼,第一次接触quartz,做个记录.-------jstarseven 最近在项目中,第一次在springmvc中配置实用quartz,深刻的感受到quartz带来的方便,顺手做个记录. ...

  8. AndroidStudio引入so文件

    项目中需要引入几个 so文件,但APP一直崩溃报错 java.lang.UnsatisfiedLinkError: Couldn't load ad from loader dalvik.system ...

  9. 竞争激烈的洗衣O2O

    今日,洗衣O2O干洗客宣布已获得千万美金Pre-A轮融资,投资方为新加坡某资本,具体信息尚不便透露. “干洗客”是36氪此前报道过的洗衣O2O服务商,2013年7月诞生于上海,2014年12月经历重组 ...

  10. .PHP后缀大写导致Linux下Composer找不到类

    在本地Windows写完一个Composer包,上传到Linux报错找不到类,纠结了一下午,最后发现是.PHP后缀大写导致的问题. mv Google2FA.PHP Google2FA.php