gson 安卓 java_Android使用Gson的总结

先说一下gson的使用方法,可以参考这篇帖子,写的很详细,感谢作者,以下内容是根据原作者帖子进行总结的自己的笔记

简要总结

Gson提供了fromJson() 和toJson() 两个直接用于解析和生成的方法,前者实现反序列化,后者实现了序列化。同时每个方法都提供了重载方法,我常用的总共有5个。

Gson gson = new Gson();

int i = gson.fromJson("100", int.class); //100

double d = gson.fromJson("\"99.99\"", double.class); //99.99

boolean b = gson.fromJson("true", boolean.class); // true

String str = gson.fromJson("String", String.class); // String

使用@SerializedName 注解重新命名字段名称

这对于使用PHP作为后台开发语言时很常见的情况,php和js在命名时一般采用下划线风格,而Java中一般采用的驼峰法,让后台的哥们改吧 前端和后台都不爽,但要自己使用下划线风格时我会感到不适应,怎么办?难到没有两全齐美的方法么?

我们知道Gson在序列化和反序列化时需要使用反射,说到反射就不得不想到注解,一般各类库都将注解放到annotations包下,打开源码在com.google.gson包下果然有一个annotations,里面有一个SerializedName的注解类,这应该就是我们要找的。

那么对于json中email_address这个属性对应POJO的属性则变成

@SerializedName("email_address")

public String emailAddress;

对于有多个字段都需要重新命名时,SerializedName注解提供了两个属性,上面用到了其中一个,别外还有一个属性alternate,接收一个String数组。

注:alternate需要2.4版本

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

public String emailAddress;

当上面的三个属性(email_address、email、emailAddress)中出现任意一个时均可以得到正确的结果

泛型擦除

Gson解析数组的时候,比较方便,例如

["Android","Java","PHP"]

直接解析

Gson gson = new Gson();

String jsonArray = "[\"Android\",\"Java\",\"PHP\"]";

String[] strings = gson.fromJson(jsonArray, String[].class);

但对于List将上面的代码中的 String[].class 直接改为 List.class 是行不通的。对于Java来说List 和List 这俩个的字节码文件只一个那就是List.class,这是Java泛型使用时要注意的问题 泛型擦除。

为了解决的上面的问题,Gson为我们提供了TypeToken来实现对泛型的支持,所以当我们希望使用将以上的数据解析为List时需要这样写。

Gson gson = new Gson();

String jsonArray = "[\"Android\",\"Java\",\"PHP\"]";

String[] strings = gson.fromJson(jsonArray, String[].class);//解析成数组

List list = gson.fromJson(jsonArray, new TypeToken>() {}.getType());//解析成集合

针对服务器返回数据的封装

有下面两种数据,我们需要的是data,code只用一次,message基本不用,那么针对data,第一个是bean,第二个则是数组,为了形象,暂且理解为第一个是User,第二个是List

"code":"0","message":"success","data":{}}

{"code":"0","message":"success","data":[]}

那么不适用泛型封装的时候,我们的字典类一定是这么写

public class UserResponse {

public int code;

public String message;

public User data;

}

public class UserResponseList {

public int code;

public String message;

public List list;

}

蓝后,我们的解析是这么写

Gson gson = new Gson();

//解析bean

UserResult userResult = gson.fromJson(json,UserResponse .class);

User user = userResult.data;

//解析集合

UserResponseList userList= gson.fromJson(json,UserResponseList .class);

List users = userList.data;

所以如果一两个还行,等真正上项目的时候,那就无语了;那么使用泛型针对返回数据进行封装了?

可以看到,公共的字段是code和message,也就是说每个后台返回来的json数据格式都是这种格式,我们就可以把公共的部分抽取出来,至于data我们不知道到底返回的是单独的字典,还是集合,还是数组,所以采用泛型

public class Result {

public int code;

public String message;

public T data;

}

这时候对于data字段是User时则可以写为 Result ,当是个列表的时候为 Result>,其它同理。

解析的时候

Type userType = new TypeToken>(){}.getType();

Result userResult = gson.fromJson(json,userType);

User user = userResult.data;

Type userListType = new TypeToken>>(){}.getType();

Result> userListResult = gson.fromJson(json,userListType);

List users = userListResult.data;

这样就解决了服务器返回数据的封装

Gson的一些配置

Gson gson = new GsonBuilder()

//序列化null

.serializeNulls()

// 设置日期时间格式,另有2个重载方法

// 在序列化和反序化时均生效

.setDateFormat("yyyy-MM-dd")

// 禁此序列化内部类

.disableInnerClassSerialization()

//生成不可执行的Json(多了 )]}' 这4个字符)

.generateNonExecutableJson()

//禁止转义html标签

.disableHtmlEscaping()

//格式化输出

.setPrettyPrinting()

.create();

基于Gson系列化json的踩坑

在三星note2(Android4.3)手机上面,使用webView.loadUrl(url)这个方法给js回传一个String类型的base64图片,发现js根本就没有拿到这个base64,经过debug,发现使用Gson.toJson方法,生成的字符串自动给价格换行符\n,各种找了一圈都没有发现问题,最后在Gson初始化这里

public static Gson getGson() {

if (null == gson) {

synchronized (GsonUtils.class) {

if (null == gson) {

GsonBuilder builder = new GsonBuilder().disableHtmlEscaping().setPrettyPrinting();

gson = builder.setDateFormat("yyyy-MM-dd HH:mm:ss").create();//.setFieldNamingStrategy(new AnnotateNaming()).create();

}

}

}

return gson;

}

发现后面多了个.setPrettyPrinting();这个方法,意思是格式化输出,去掉这个,\n没有了,再次传的时候发现问题解决

这个问题在4.4及以上没有发现,应该是系统问题,4.3及以前的webView用的是WebKit内核,从4.4开始使用的是Chrome内核,4.3的loadUrl方法传进去的字符串不能含有转义?等翻了源码再确定一下这个问题

总结

通过踩坑,总结几点:

在做适配的时候,首先要排除系统问题,认真记录一下操作系统的版本

做最小化测试,首先从最简单的开始排除;

例如此坑中,传递的base64字符串特别大,算了一下大概有8万个字符,刚开始怀疑是字符太多,就做实验,写了一个循环,使用StringBuilder每次添加1万个字符进去,发现到10万都没问题,这样就排除了大小限制;然后再就是排除特殊符号,比如'' /r/n \r\n 等等;一个个去排除;最后发现就是特殊字符引起的.

3.认真做好每次踩坑的笔记

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值