json-libのjsonConfig詳細使用

11349 ワード

一、setCycleDetectionStrategy自己包含防止
 /**
     *                 CycleDetectionStrategy
     */
    public static void testCycleObject() {
        CycleObject object = new CycleObject();
        object.setMemberId("yajuntest");
        object.setSex("male");
        JsonConfig jsonConfig = new JsonConfig();
        jsonConfig.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);

        JSONObject json = JSONObject.fromObject(object, jsonConfig);
        System.out.println(json);
    }

    public static void main(String[] args) {
               JsonTest.testCycleObject();
    }

 CycleObject.javaは自分で書いたクラスです.
public class CycleObject {

    private String      memberId;
    private String      sex;
    private CycleObject me = this;
…… // getters && setters
}

 
二、setExcludes:jsonにシーケンス化する必要がある属性を除外する
 public static void testExcludeProperites() {
        String str = "{'string':'JSON', 'integer': 1, 'double': 2.0, 'boolean': true}";
        JsonConfig jsonConfig = new JsonConfig();
        jsonConfig.setExcludes(new String[] { "double", "boolean" });
        JSONObject jsonObject = (JSONObject) JSONSerializer.toJSON(str, jsonConfig);
        System.out.println(jsonObject.getString("string"));
        System.out.println(jsonObject.getInt("integer"));
        System.out.println(jsonObject.has("double"));
        System.out.println(jsonObject.has("boolean"));
    }

    public static void main(String[] args) {
        JsonTest.testExcludeProperites();
    }

 
三、setIgnoreDefaultExcludes
@SuppressWarnings("unchecked")
	public static void testMap() {
		Map map = new HashMap();
		map.put("name", "json");
		map.put("class", "ddd");
		JsonConfig config = new JsonConfig();
		config.setIgnoreDefaultExcludes(true);  //   false,      key
		JSONObject jsonObject = JSONObject.fromObject(map,config);
		System.out.println(jsonObject);
		
	}

 
上のコードはnameとclassを出力します.
setIgnoreDefaultExcludes(true)を外すとnameしか出力されずclassは出力されません.
   private static final String[] DEFAULT_EXCLUDES = new String[] { "class", "declaringClass",
         "metaClass" }; //         key

 
四、registerJsonBeanProcessor valueタイプがjavaのbeanから変換されたとき、カスタムプロセッサを提供することができます.
 
 
	public static void testMap() {
		Map map = new HashMap();
		map.put("name", "json");
		map.put("class", "ddd");
		map.put("date", new Date());
		JsonConfig config = new JsonConfig();
		config.setIgnoreDefaultExcludes(false);
		config.registerJsonBeanProcessor(Date.class,
				new JsDateJsonBeanProcessor()); //         ,   JS       
		JSONObject jsonObject = JSONObject.fromObject(map, config);
		System.out.println(jsonObject);
	}

 
 注意:JsDateJsonBeanProcessorはjson-libがすでに提供しているクラスで、私たちも自分のJsonBeanProcessorを実現することができます.
五、registerJsonValueProcessor
 
六、registerDefaultValueProcessor
 
プレゼンテーションのために、まず自分で2つ実現しました. Processor
Integer向け
 
public class MyDefaultIntegerValueProcessor implements DefaultValueProcessor {

	public Object getDefaultValue(Class type) {
		if (type != null && Integer.class.isAssignableFrom(type)) {
			return Integer.valueOf(9999);
		}
		return JSONNull.getInstance();
	}

}

 
PlainObject(カスタムクラス)
public class MyPlainObjectProcessor implements DefaultValueProcessor {

	public Object getDefaultValue(Class type) {
		if (type != null && PlainObject.class.isAssignableFrom(type)) {
			return "  " + "  ";
		}
		return JSONNull.getInstance();
	}
}

 
以上の2つのクラスは、valueがnullの場合にどのように出力するかを処理するために使用されます.
 
普通のカスタムbeanも2つ用意されています
PlainObjectHolder:
 
public class PlainObjectHolder {

	private PlainObject object; //      
	private Integer a; // JDK     

	public PlainObject getObject() {
		return object;
	}

	public void setObject(PlainObject object) {
		this.object = object;
	}

	public Integer getA() {
		return a;
	}

	public void setA(Integer a) {
		this.a = a;
	}

}

 
PlainObject 自分で定義したクラスです
public class PlainObject {

    private String memberId;
    private String sex;

    public String getMemberId() {
        return memberId;
    }

    public void setMemberId(String memberId) {
        this.memberId = memberId;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

}

 
A,JSONObject.fromObject(null)というパラメータがnullに直接送られたら、json-libはどうしますか.
 public static JSONObject fromObject( Object object, JsonConfig jsonConfig ) {
      if( object == null || JSONUtils.isNull( object ) ){
         return new JSONObject( true );

 
コードを見ると、空のJSOnObjectが直接返され、デフォルト値の出力は使用されません.
 
B,次に,Javaオブジェクトが直接JDKに存在するクラス(Enum,Annotation,JSOnObject,DynaBean,JSOnTokener,JSOnString,Map,String,Number,Arrayとは何か)である場合を見るが,null,json-libはどのように処理するか
 JSONObject.java
  }else if( object instanceof Enum ){
         throw new JSONException( "'object' is an Enum. Use JSONArray instead" ); //      
      }else if( object instanceof Annotation || (object != null && object.getClass()
            .isAnnotation()) ){
         throw new JSONException( "'object' is an Annotation." ); //       
      }else if( object instanceof JSONObject ){
         return _fromJSONObject( (JSONObject) object, jsonConfig );
      }else if( object instanceof DynaBean ){
         return _fromDynaBean( (DynaBean) object, jsonConfig );
      }else if( object instanceof JSONTokener ){
         return _fromJSONTokener( (JSONTokener) object, jsonConfig );
      }else if( object instanceof JSONString ){
         return _fromJSONString( (JSONString) object, jsonConfig );
      }else if( object instanceof Map ){
         return _fromMap( (Map) object, jsonConfig );
      }else if( object instanceof String ){
         return _fromString( (String) object, jsonConfig );
      }else if( JSONUtils.isNumber( object ) || JSONUtils.isBoolean( object )
            || JSONUtils.isString( object ) ){
         return new JSONObject();  //       
      }else if( JSONUtils.isArray( object ) ){
         throw new JSONException( "'object' is an array. Use JSONArray instead" ); //     ,   JSONArray  
      }else{

 
以上のコードにより、主な発見_fromMapではDefaultValueProcessorの使用はサポートされていません.
理由コード:
JSONObject.java
 if( value != null ){ //      ,value   
               JsonValueProcessor jsonValueProcessor = jsonConfig.findJsonValueProcessor(
                     value.getClass(), key );
               if( jsonValueProcessor != null ){
                  value = jsonValueProcessor.processObjectValue( key, value, jsonConfig );
                  if( !JsonVerifier.isValidJsonValue( value ) ){
                     throw new JSONException( "Value is not a valid JSON value. " + value );
                  }
               }
               setValue( jsonObject, key, value, value.getClass(), jsonConfig );

 
 private static void setValue( JSONObject jsonObject, String key, Object value, Class type,
         JsonConfig jsonConfig ) {
      boolean accumulated = false;
      if( value == null ){ //   value       DefaultValueProcessor
         value = jsonConfig.findDefaultValueProcessor( type )
               .getDefaultValue( type );
         if( !JsonVerifier.isValidJsonValue( value ) ){
            throw new JSONException( "Value is not a valid JSON value. " + value );
         }
      }
……

 
私のコメントによると、 上のコードには明らかに矛盾がある.
 
_fromDynaBeanはDefaultValueProcessorをサポートしていますが、次のCと同じです.
 
C,javaオブジェクトがカスタムタイプであり,中の属性に空の値(値が割り当てられていない,デフォルトはnull)が含まれている場合,上のBがまだ貼り付けられていない最後のelseである.
else {return _fromBean( object, jsonConfig );}

 
テストクラスを書きました.
 
 
public static void testDefaultValueProcessor() {
		PlainObjectHolder holder = new PlainObjectHolder();
		JsonConfig config = new JsonConfig();
		config.registerDefaultValueProcessor(PlainObject.class,
				new MyPlainObjectProcessor());
		config.registerDefaultValueProcessor(Integer.class,
				new MyDefaultIntegerValueProcessor());
		JSONObject json = JSONObject.fromObject(holder, config);
		System.out.println(json);
	}

 
この場合の出力値は{"a":9999,"object":"美女瑶瑶"}つまり2つのProcessorが機能します.
 
 
 
========================== Json To Java ===============
 
 
一、ignoreDefaultExcludes
 
public static void json2java() {
		String jsonString = "{'name':'hello','class':'ddd'}";
		JsonConfig config = new JsonConfig();
		config.setIgnoreDefaultExcludes(true); //  JAVA To Json     ,   class      
		JSONObject json = (JSONObject) JSONSerializer.toJSON(jsonString,config);
		System.out.println(json);
	}

 
==========================================
私たちがプログラムを作るときは主にJava To Jsonを使う方法で、以下はセキュリティの問題を説明します.
 @SuppressWarnings("unchecked")
    public static void testSecurity() {
        Map map = new HashMap();
        map.put("\"}<IMG src='x.jpg' onerror=javascript:alert('       ') border=0> {", "");
        JSONObject jsonObject = JSONObject.fromObject(map);
        System.out.println(jsonObject);
    }

 
 public static void main(String[] args) {
        JsonTest.testSecurity();
    }

 
 出力内容:
 
{""}{":"""}
 
この内容を直接メモ帳に貼り付けてtestSecu.htmlと名付け、ブラウザでjsスクリプトが実行されていることを発見します.これにより、XSSセキュリティの問題が発生しやすくなります.