GSON属性个性化定制

nalanrumeng 2014-07-02

有时候我们不需要把实体的所有属性都导出,只想把一部分属性导出为Json.

有时候我们的实体类会随着版本的升级而修改.

有时候我们想对输出的json默认排好格式.

... ...

请看下面的例子吧:

实体类:

public enum ClientIdEnum {
    APP_GAME(1) // 1:应用中心
    , KITTYPLAY_2V(22) // 22:美化中心
    ;
    private final int value;

    private ClientIdEnum(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}
public class AppInfo {
	
	public String name;//针对所有产品
	
	@ClientLimit(closeAll = true)
	public String extendMes ;//屏蔽所有产品
	
	@ClientLimit(open = {ClientIdEnum.KITTYPLAY_2V,ClientIdEnum.APP_GAME})
	public String pic;//只针对 美化中心/应用中心 产品
	
	@ClientLimit(close = {ClientIdEnum.APP_GAME})
	public Mes mes = new Mes();//只针对 应用中心 产品

	@Since(value = 1.3)
	public String imgs;//只针对 >=1.3 版本号的所有产品
	
	@Until(value = 1.2)
	public String banner;//只针对 <1.2 版本号的所有产品
	
	public AppInfo(){
		this.name = "应用宝";
		this.pic = "http://pic.png";
		this.imgs = "http://imgs1.png#http://imgs2.png";
		this.banner = "http://banner.png";
		this.extendMes = "备注信息";
	}
}
@Target({ElementType.FIELD}) 
@Retention(RetentionPolicy.RUNTIME) 
@Documented 
@Inherited
public @interface ClientLimit {
	/**
	 * @Title: open
	 * @Description:  定义需开放的产品,进行json转换
	 * @param @return    设定文件
	 * @return ClientIdEnum[]    返回类型
	 * @throws
	 */
	ClientIdEnum[] open() default {};
	
	/**
	 * @Title: close
	 * @Description: 定义需关闭的产品,不进行json转换
	 * @param @return    设定文件
	 * @return ClientIdEnum[]    返回类型
	 * @throws
	 */
	ClientIdEnum[] close() default {};
	
	/**
	 * @Title: closeAll
	 * @Description: 定义关闭所有产品,不进行json转换
	 * @param @return    设定文件
	 * @return boolean    返回类型
	 * @throws
	 */
	boolean closeAll() default false;
}
public class ClientIdExclusionStrategy implements ExclusionStrategy {

	private ClientIdEnum clientId = null;
	
	public ClientIdExclusionStrategy(ClientIdEnum clientId){
		this.clientId = clientId;
	}
	@Override
	public boolean shouldSkipField(FieldAttributes f) {
		boolean filter = false;
		
		ClientLimit clientLimit = f.getAnnotation(ClientLimit.class);
		if(clientLimit != null){
			boolean closeAll = clientLimit.closeAll();
			if(closeAll){
				filter = true;
			}else {
				ClientIdEnum[] open = clientLimit.open();
				ClientIdEnum[] close = clientLimit.close();
				if(open.length > 0){
					filter = true;
					for(ClientIdEnum clientIdEnum:open){
						if(clientId == clientIdEnum){
							filter = false;
							break;
						}
					}
				}else if (close.length > 0) {
					filter = false;
					for(ClientIdEnum clientIdEnum:close){
						if(clientId == clientIdEnum){
							filter = true;
							break;
						}
					}
				}
			}
		}
		return filter;
	}

	@Override
	public boolean shouldSkipClass(Class<?> clazz) {
		// TODO Auto-generated method stub
		return false;
	}

}
public class Test  extends TestCase{

	public void testGson(){
		AppInfo appInfo = new AppInfo();
		//注意这里的Gson的构建方式为GsonBuilder,区别于test1中的Gson gson = new Gson();  
        Gson gson = new GsonBuilder()  
//        .excludeFieldsWithoutExposeAnnotation() //不导出实体中没有用@Expose注解的属性  
        .enableComplexMapKeySerialization() //支持Map的key为复杂对象的形式  
        .serializeNulls() //若对象为null,则进行 null 转换;默认null值不进行转换
        .setDateFormat("yyyy-MM-dd HH:mm:ss:SSS")//时间转化为特定格式    
//        .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)//会把字段首字母大写,注:对于实体上使用了@SerializedName注解的不会生效.  
        .setPrettyPrinting() //对json结果格式化.  
        .setVersion(1.2)    //有的字段不是一开始就有的,会随着版本的升级添加进来,那么在进行序列化和返序列化的时候就会根据版本号来选择是否要序列化.  
                            //@Since(版本号)能完美地实现这个功能.还的字段可能,随着版本的升级而删除,那么  
                            //@Until(版本号)也能实现这个功能,GsonBuilder.setVersion(double)方法需要调用.  
        .setExclusionStrategies(new ClientIdExclusionStrategy(ClientIdEnum.APP_GAME))//自定义属性过滤器
//        .registerTypeAdapter(type, typeAdapter) //自定义适配器,对属性类型为 type类型的,进行typeAdapter转换,如时间格式化等 
        .create(); 
        System.out.println(gson.toJson(appInfo));
	}
}

相关推荐