jsonconfig详解

一,setCycleDetectionStrategy 防止自包含

Java代码
  1. /**
  2. *这里测试如果含有自包含的时候需要CycleDetectionStrategy
  3. */
  4. publicstaticvoidtestCycleObject(){
  5. CycleObjectobject=newCycleObject();
  6. object.setMemberId("yajuntest");
  7. object.setSex("male");
  8. JsonConfigjsonConfig=newJsonConfig();
  9. jsonConfig.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);
  10. JSONObjectjson=JSONObject.fromObject(object,jsonConfig);
  11. System.out.println(json);
  12. }
  13. voidmain(String[]args){
  14. JsonTest.testCycleObject();
  15. }

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

classCycleObject{
  • privateStringmemberId;
  • privateStringsex;
  • privateCycleObjectme=this;
  • ……//getters&&setters
  • 输出 {"sex":"male","memberId":"yajuntest","me":null}

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

    voidtestExcludeProperites(){
  • Stringstr="{'string':'JSON','integer':1,'double':2.0,'boolean':true}";
  • jsonConfig.setExcludes(newString[]{"double","boolean"});
  • JSONObjectjsonObject=(JSONObject)JSONSerializer.toJSON(str,255); background-color:inherit">System.out.println(jsonObject.getString("string"));
  • System.out.println(jsonObject.getInt("integer"));
  • System.out.println(jsonObject.has("double"));
  • "boolean"));
  • JsonTest.testExcludeProperites();
  • 三,setIgnoreDefaultExcludes

    @SuppressWarnings("unchecked")
  • voidtestMap(){
  • Mapmap=newHashMap();
  • map.put("name",0); background-color:inherit">"json");
  • "class",0); background-color:inherit">"ddd");
  • JsonConfigconfig=config.setIgnoreDefaultExcludes(true);//认为false,即过滤认的key
  • JSONObjectjsonObject=JSONObject.fromObject(map,config);
  • System.out.println(jsonObject);
  • 上面的代码会把name 和 class都输出

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

    privatefinalString[]DEFAULT_EXCLUDES="declaringClass",
  • "MetaClass"};//认会过滤的几个key
  • 四,registerjsonBeanProcessor 当value类型是从java的一个bean转化过来的时候,可以提供自定义处理器

    "date",newDate());
  • false);
  • config.registerjsonBeanProcessor(Date.class,0); background-color:inherit; font-weight:bold">newJsDateJsonBeanProcessor());//当输出时间格式时,采用和JS兼容的格式输出
  • 注:JsDateJsonBeanProcessor 是json-lib已经提供的类,我们也可以实现自己的JsonBeanProcessor。

    五,registerjsonValueProcessor

    六,registerDefaultValueProcessor

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

    一个针对Integer

    classMyDefaultIntegerValueProcessorimplementsDefaultValueProcessor{
  • publicObjectgetDefaultValue(Classtype){
  • if(type!=null&&Integer.class.isAssignableFrom(type)){
  • returnInteger.valueOf(9999);
  • returnJSONNull.getInstance();
  • 一个针对PlainObject(我自定义的类)

    classMyPlainObjectProcessornull&&PlainObject.return"美女"+"瑶瑶";
  • 以上两个类用于处理当value为null的时候该如何输出

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

    PlainObjectHolder:

    classPlainObjectHolder{
  • privatePlainObjectobject;//自定义类型
  • privateIntegera;//JDK自带的类型
  • publicPlainObjectgetobject(){
  • returnobject;
  • voidsetobject(PlainObjectobject){
  • this.object=object;
  • publicIntegergetA(){
  • returna;
  • voidsetA(Integera){
  • this.a=a;
  • PlainObject也是我自己定义的类

    classPlainObject{
  • publicStringgetMemberId(){
  • returnmemberId;
  • voidsetMemberId(StringmemberId){
  • this.memberId=memberId;
  • publicStringgetSex(){
  • returnsex;
  • voidsetSex(Stringsex){
  • this.sex=sex;
  • A,如果JSONObject.fromObject(null) 这个参数直接传null进去,json-lib会怎么处理:

    staticJSONObjectfromObject(Objectobject,JsonConfigjsonConfig){
  • if(object==null||JSONUtils.isNull(object)){
  • returnnewJSONObject(true);
  • 代码是直接返回了一个空的JSONObject,没有用到任何认值输出

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

    JSONObject.java

    }elseif(objectinstanceofEnum){
  • thrownewJSONException("'object'isanEnum.UseJSONArrayinstead");//不支持枚举
  • }instanceofAnnotation||(object!=null&&object.getClass()
  • .isAnnotation())){
  • "'object'isanAnnotation.");//不支持注解
  • instanceofJSONObject){
  • return_fromJSONObject((JSONObject)object,jsonConfig);
  • instanceofDynaBean){
  • return_fromDynaBean((DynaBean)object,0); background-color:inherit; font-weight:bold">instanceofJSONTokener){
  • return_fromJSONTokener((JSONTokener)object,0); background-color:inherit; font-weight:bold">instanceofJSONString){
  • return_fromJSONString((JSONString)object,0); background-color:inherit; font-weight:bold">instanceofMap){
  • return_fromMap((Map)object,0); background-color:inherit; font-weight:bold">instanceofString){
  • return_fromString((String)object,0); background-color:inherit; font-weight:bold">if(JSONUtils.isNumber(object)||JSONUtils.isBoolean(object)
  • ||JSONUtils.isstring(object)){
  • newJSONObject();//不支持纯数字
  • if(JSONUtils.isArray(object)){
  • "'object'isanarray.UseJSONArrayinstead");//不支持数组,需要用JSONArray替代
  • else{
  • 根据以上代码,主要发现_fromMap是不支持使用DefaultValueProcessor 的。

    原因看代码

    if(value!=null){//大的前提条件,value不为空

  • JsonValueProcessorjsonValueProcessor=jsonConfig.findJsonValueProcessor(
  • value.getClass(),key);
  • if(jsonValueProcessor!=null){
  • value=jsonValueProcessor.processObjectValue(key,value,0); background-color:inherit; font-weight:bold">if(!JsonVerifier.isValidJsonValue(value)){
  • "ValueisnotavalidJSONvalue."+value);
  • setValue(jsonObject,key,value.getClass(),jsonConfig);
  • voidsetValue(JSONObjectjsonObject,Stringkey,Objectvalue,Classtype,255); background-color:inherit">JsonConfigjsonConfig){
  • booleanaccumulated=false;
  • if(value==//当value为空的时候使用DefaultValueProcessor
  • value=jsonConfig.findDefaultValueProcessor(type)
  • .getDefaultValue(type);
  • ……
  • 根据我的注释,上面的代码显然是存在矛盾。

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

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

    else{return_fromBean(object,jsonConfig);}

    我写了个测试类:

    voidtestDefaultValueProcessor(){
  • PlainObjectHolderholder=newPlainObjectHolder();
  • config.registerDefaultValueProcessor(PlainObject.newMyPlainObjectProcessor());
  • config.registerDefaultValueProcessor(Integer.newMyDefaultIntegerValueProcessor());
  • JSONObjectjson=JSONObject.fromObject(holder,43); font-family:Arial; font-size:14.44444465637207px; line-height:25.98958396911621px"> 这种情况的输出值是 {"a":9999,"object":"美女瑶瑶"}
    即两个Processor都起作用了。

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

    一,ignoreDefaultExcludes

    voidjson2java(){
  • StringjsonString="{'name':'hello','class':'ddd'}";
  • //与JAVAToJson的时候一样,不设置class属性无法输出
  • JSONObjectjson=(JSONObject)JSONSerializer.toJSON(jsonString,43); font-family:Arial; font-size:14.44444465637207px; line-height:25.98958396911621px"> ========================== JSON 输出的安全问题 ===============

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

    voidtestSecurity(){

  • "/"}<IMGsrc='x.jpg'onerror=javascript:alert('说了你不要进来')border=0>{",0); background-color:inherit">"");
  • JSONObjectjsonObject=JSONObject.fromObject(map);
  • }
  • JsonTest.testSecurity();
  • 输出内容

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

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

  • 相关文章

    AJAX是一种基于JavaScript和XML的技术,能够使网页实现异步交...
    在网页开发中,我们常常需要通过Ajax从后端获取数据并在页面...
    在前端开发中,经常需要循环JSON对象数组进行数据操作。使用...
    AJAX(Asynchronous JavaScript and XML)是一种用于创建 We...
    AJAX技术被广泛应用于现代Web开发,它可以在无需重新加载页面...
    Ajax是一种通过JavaScript和HTTP请求交互的技术,可以实现无...