Gson使用总结

参考(不限于):http://www.jianshu.com/p/e740196225a4

1.使用@SerializedName,处理客户端与服务端字段明命名不一致

@SerializedName(value = "emailAddress", alternate = {"email", "email_address"})
public String emailAddress;

2.使用TypeToken,处理泛型擦除

//方法声明
public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {  Object object = fromJson(json, (Type) classOfT);  return Primitives.wrap(classOfT).cast(object);}

Gson gson = new Gson();
String jsonArray = "[\"Android\",\"Java\",\"PHP\"]";
String[] strings = gson.fromJson(jsonArray, String[].class);
//错误写法
List<String> strings =gson.fromJson(jsonArray, String[].class); 
//正确写法
List<String> stringList = gson.fromJson(jsonArray, new TypeToken<List<String>>() {}.getType());

3.使用泛型,改善POJO的设计

//原设计
public class UserResult {    
    public int code;    
    public String message;    
    public User data;
}
public class UserListResult {    
    public int code;    
    public String message;    
    public List<User> data;
}
String json = "{..........}";
Gson gson = new Gson();
UserResult userResult = gson.fromJson(json,UserResult.class);
User user = userResult.data;UserListResult userListResult = gson.fromJson(json,UserListResult.class);
List<User> users = userListResult.data;
//新设计
public class Result<T> {    
    public int code;    
    public String message;      
    public T data;
}
Type userType = new TypeToken<Result<User>>(){}.getType();
Result<User> userResult = gson.fromJson(json,userType);User user = userResult.data;
Type userListType = new TypeToken<Result<List<User>>>(){}.getType();
Result<List<User>> userListResult = gson.fromJson(json,userType);
List<User> users = userListResult.data;

4.使用GsonBuilder导出null值、格式化输出、日期时间

Gson gson = new GsonBuilder()        
//序列化null        
.serializeNulls()        
// 设置日期时间格式,另有2个重载方法        
// 在序列化和反序化时均生效 
.setDateFormat("yyyy-MM-dd")        
// 禁此序列化内部类       
.disableInnerClassSerialization()        
//生成不可执行的Json(多了 )]}' 这4个字符)        
.generateNonExecutableJson()        
//禁止转义html标签        
.disableHtmlEscaping()        
//格式化输出        
.setPrettyPrinting()        
.create();

4.排除无用的字段

方案1.使用transient关键字

方案2.使用Modifier为指定类型的字段(excludeFieldsWithModifiers(Modifier.PROTECTED))

方案3.使用@Expose,过滤无用(业务)字段

public class Category {    
  @Expose    
  public int id;    
  @Expose 
  public String name;    
  @Expose 
  public List<Category> children;    
  //不需要序列化,所以不加 @Expose 注解,    
  //等价于 @Expose(deserialize = false,serialize = false)    
  public Category parent;
}
Gson gson = new GsonBuilder()  
      .excludeFieldsWithoutExposeAnnotation() 
      .create();
gson.toJson(category);

方案4.基于策略(自定义规则),过滤无用(业务)字段

Gson gson = new GsonBuilder() 
      .addSerializationExclusionStrategy(new ExclusionStrategy() {            
        @Override            
        public boolean shouldSkipField(FieldAttributes f) { 
           // 这里作判断,决定要不要排除该字段,return true为排除               
           if ("finalField".equals(f.getName())) return true; 
           //按字段名排除                
           Expose expose = f.getAnnotation(Expose.class);                
           if (expose != null && expose.deserialize() == false) 
             return true; 
            //按注解排除          
         return false;           
       }            
       @Override            
       public boolean shouldSkipClass(Class<?> clazz) {                
         // 直接排除某个类 ,return true为排除                    
         return (clazz == int.class || clazz == Integer.class);            }        
       })        
.create();

5.处理混合类型的bean

//原json
{
    "timestamp": 1449199363.89387,
    "message": "Succeed",
    "version": "1.0",
    "results": [
        {
            "data": {
                "recommended": 0,
                "video_type": 2,
                "vid": "23482078",
                "title": "破风",
                "movie_title": "破风",
                "duration": "126",
                "is_voted": 0,
                "image": "http://i1.letvimg.com/lc02_isvrs/201509/11/16/21/a4bdc7ff-6d69-4875-bff8-dbe136a533ff/thumb/2_960_540.jpg",
                "playcount": 3303475,
                "share_link": "http://leying.duohappy.cn",
                "desc": "无畏“破风手”传递正能量",
                "code_rate": [
                    9,
                    13,
                    21,
                    22,
                    51
                ],
                "is_downloadable": 0
            },
            "type": "video"
        },
        {
            "data": {
                "url": "http://www.baidu.com/",
                "image": "http://i0.letvimg.com/lc02_isvrs/201506/11/16/26/dbbebacb-12f5-4356-a364-c9a888b884ba/thumb/2_1440_810.jpg",
                "desc": "测试跳转描述",
                "recommended": 1,
                "title": "测试跳转"
            },
            "type": "link"
        }
    ]
}

问题点是这个data数据,由于返回data数据,受到type的影响。无法固定List<T> 里的泛型T,只能用Object来代替。实际运行List里面的object,可能是video,也可能是link。需要自己定义json的反序列化过程。即实现JsonDeserializer接口,代码如下。

public class VideoList {
    public float timestamp;
    public String message;
    public String version;
    public List<Object> results;
}
public class VideoBean {
}
public class ChooseH5Bean {
}

public class VideoListJsonDeserializer implements JsonDeserializer<VideoList> {
        @Override
        public VideoList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            VideoList videoList = new VideoList();
            if (json.isJsonObject()) {
                JsonObject jsonObject = json.getAsJsonObject();

                videoList.timestamp = jsonObject.get("timestamp").getAsFloat();
                videoList.message = jsonObject.get("message").getAsString();
                videoList.version = jsonObject.get("version").getAsString();

                JsonArray array = (JsonArray) jsonObject.get("results");
                List<Object> list = new ArrayList<Object>();
                for (int i = 0; i < array.size(); i++) {
                    JsonObject element = (JsonObject) array.get(i);
                    String type = element.get("type").getAsString();
                    Object item = null;
                    if ("video".equals(type)) {
                        item = context.deserialize(element.getAsJsonObject("data"), Video.class);
                    } else if ("link".equals(type)) {
                        item = context.deserialize(element.getAsJsonObject("data"), Link.class);
                    }
                    if (item != null) {
                        list.add(item);
                    }
                }
                videoList.results = list;
            }

            return videoList;
        }
    }

方案1.注册TypeAdapter

Gson gson = new GsonBuilder().registerTypeAdapter(VideoList.class, new VideoListJsonDeserializer()).create();
InputStream inputStream = getResources().openRawResource(R.raw.text);
VideoList videoList = gson.fromJson(new InputStreamReader(inputStream), VideoList.class);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,045评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,114评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,120评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,902评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,828评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,132评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,590评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,258评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,408评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,335评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,385评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,068评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,660评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,747评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,967评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,406评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,970评论 2 341

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,566评论 18 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,537评论 18 399
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,279评论 25 707
  • 此生,也许你无法去企及向日葵的高度。却依然用尽全力,散发出向日葵的味道。 然后,穿枝拂叶,布施阳光。 01 他,一...
    上官小姐阅读 385评论 2 5
  • 在这样忙忙碌碌或者碌碌无为的生活里,你会不会觉得有时太过疲累。像是一名伏尔加河畔的纤夫,被一把看不见的鞭子,抽打着...
    攸宁攸殇阅读 1,150评论 3 14