在android里面,肯定离不开数据的解析,对网络请求获取到的json格式进行数据解析,一般使用的比较广泛的有gson、fastJson、jackJson。关于各个工具包的性能比较网络上很多,随便一搜一大把,这里对gson做一个使用的介绍,平时用到的也就这么几个方法,花费了一些时间学习的东西,用的少就容易忘记,是该捡一捡做做记录了。
1.json格式,是用来交换文本形式的数据
2.前两种在google play Top200中使用率57%,可见gson的比重是相当的大。
3.gson使用的下载地址https://github.com/google/gson
4.gson提供了两个直接用于生成和解析json的方法,toJson()实现序列号,fromJson()实现了反序列化。
基本的用法
1.解析基本数据类型--最基本的方式
1,下面可以看到把最基本的数据类型解析出来
public void fromJson(){
Gson gson = new Gson();
int i = gson.fromJson("100", int.class);
double d = gson.fromJson("\"9.9\"", double.class);
boolean b = gson.fromJson("true", boolean.class);
String s = gson.fromJson("string",String.class);
Log.i("gson", " i=" + i + " d=" + d + " b=" + b+" s=" + s);
}
<pre name="code" class="java">打印的结果是 i=100 d=9.9 b=true s=string
2.生成基本数据类型
public void toJson(){
Gson gson = new Gson();
String num = gson.toJson(100);
String bool = gson.toJson(false);
String str = gson.toJson("String");
Log.i("gson", "打印的结果是 num=" + num + " bool=" + bool + " str=" + str);
}
打印的结果是 num=100 bool=false str="String"
2.下面是稍微复杂一点简单的java对象,生成与解析
1.先写一个简单的bean
public class UserBean {
private String name;
private int age;
public UserBean(String name, int age) {
this.name = name;
this.age = age;
}
}
2,生成json
UserBean bean = new UserBean("赵子龙",100);
String toJson = gson.toJson(bean);
Log.i("gson", "打印的结果是 toJson=" + toJson);
3,通过ben生成了json格式的数据
打印的结果是 toJson={"age":100,"name":"赵子龙"}
3.通过上面的bean将生成的json数据解析出来
1.复写bean的toString方法
public class UserBean {
private String name;
private int age;
public UserBean(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "UserBean{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
2。json生成bean对象
String fromJson = "{\"name\":\"刘玄德\",\"age\":33}";
UserBean bean = gson.fromJson(fromJson, UserBean.class);
Log.i("gson", "打印的结果是 " + bean.toString());
3.结果
打印的结果是 UserBean{name='刘玄德', age=33}
4.这个解析也可以通过手动来完成,不过我相信也没有人去这样做。
1.方式介绍
UserBean bean2 = new UserBean();
String fromJson2 = "{\"name\":\"刘玄德2\",\"age\":33}";
JsonReader reader = new JsonReader(new StringReader(fromJson2));
try {
reader.beginObject();
while (reader.hasNext()){
String s1 = reader.nextName();
switch (s1) {
case "name":
bean2.name = reader.nextString();
break;
case "age":
bean2.age = reader.nextInt();
break;
}
}
reader.endObject();
Log.i("gson", "打印的结果是 bean2= " + bean2.toString());
} catch (IOException e) {
e.printStackTrace();
}
2.结果
打印的结果是 bean2= UserBean{name='刘玄德2', age=33}
5。既然能手动解析json那么也可以手动进行生成json
1.方式
<span style="white-space:pre"> </span>JsonWriter jsonWriter = new JsonWriter(new LogWriter("gson"));
try {
jsonWriter.beginObject().name("name").value("赵子龙")
.name("age").value(100).endObject();
jsonWriter.flush();
} catch (IOException e) {
e.printStackTrace();
}
2.结果
{"name":"赵子龙","age":100}
6.接下来是注解的使用
1.不知道看到这里的例子有没有疑惑?在第一个例子中的double转换的时候有没有发现9.9也是字符串。也就是String类型,其实那里应该是这样的写的
double d = gson.fromJson("\"9.9\"", double.class);
那么为什么写成字符串也是可以的呢?是因为它又一定的容错机制,但是有时候这个机制并不可行,比如我们把bean再加一个字段email_address,这时我们所期望的json应该是
{"name":"赵子龙", "age":"100", "email_address":"utmoi@163.com"}
android中的名字都是驼峰的写法,但是这个json字段的下划线拼接的,这是的问题可以使用注解得到很好的解决
2.使用注解
public class UserBean {
public String name;
public int age;
@SerializedName("email_address") //注解方式
public String emailAddress;
public UserBean(String name, int age , String emailAddress) {
this.name = name;
this.age = age;
this.emailAddress = emailAddress;
}
@Override
public String toString() {
return "UserBean{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
这样就满足了命名规范,那么如果要是再有另一种情况怎么办?也是有解决的办法,把注解变成数组形式
public class UserBean {
public String name;
public int age;
@SerializedName(value = "emailAddress",alternate = {"email" , "email_address"})
public String emailAddress;
public UserBean(String name, int age , String emailAddress) {
this.name = name;
this.age = age;
this.emailAddress = emailAddress;
}
}
这样无论有几种形式就全能搞定。
3.多种情况同时出现的时候,以多种注解情况举例子
Gson gson = new Gson(); //多个注解地址同时出现的情况以最后一个位准
String fromJson3 = "{\"name\":\"刘玄德3\",\"age\":33,\"emailAddress\":\"utmoi@163.com\",\"email\":\"utmoi@1634.com\"}";
UserBean bean = gson.fromJson(fromJson3, UserBean.class);
Log.i("gson" , bean.toString());
4.结果
UserBean{name='刘玄德3', age=33, emailAddress='utmoi@1634.com'}
是以最后一个结果为准
7.下面在看一个方法,也是类似上面注解这种,映射规则的GsonBuilder.setFieldNamingPloicy()要配合枚举使用,同样是上面的userbean,把注解去掉,使用gsonBuilder
1.方式介绍
Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES).create();
UserBean userBean = new UserBean("赵子龙",100,"utmoi@163.com");
String toJson = gson.toJson(userBean);
Log.i("gson", "打印的结果是 toJson= " + toJson);
2.结果
打印的结果是 toJson= {"age":100,"email-address":"utmoi@163.com","name":"赵子龙"}
可以看到email的字段key值变了,但是加上了注解,那么就还是原来的样子,说明注解拥有更高的优先级,有注解存在时候这种方式不生效,枚举的类型有几种呢?
答案是有5种。
8.除了有系统枚举的实现方式,还可以自定义实现的
1.方式介绍
Gson gson = new GsonBuilder().setFieldNamingStrategy(new FieldNamingStrategy() {
@Override
public String translateName(Field f) {
if("emailAddress".equals(f.getName())){
return "email";
}
return f.getName();
}
}).create();
UserBean userBean = new UserBean("赵子龙",100,"utmoi@163.com");
String toJson = gson.toJson(userBean);
Log.i("gson", "打印的结果是 toJson= " + toJson);
2.打印结果
打印的结果是 toJson= {"age":100,"email":"utmoi@163.com","name":"赵子龙"}
1.数组的解析,把数组形式的json解析出来
Gson gson = new Gson();
String jsonArray = "[\"Swift\",\"Java\",\"PHP\"]";
String[] strings = gson.fromJson(jsonArray, String[].class);
Log.i("gson", "打印的结果是 strings[0]= " + strings[0] + " strings[1]=" + strings[1] + " strings[2]=" + strings[2]) ;
2.结果
打印的结果是 strings[0]= Swift strings[1]=Java strings[2]=PHP
3.如果不是数组形式,而是List形式,直接把String[].class换成List.class是不行的,因为List<String>和List<UserBean>的字节码文件都是一样的,都是List.class。现在就要用到泛型解析了,当解析List<String>时。
Gson gson = new Gson();
String jsonArray = "[\"Swift\",\"Java\",\"PHP\"]";
List<String> strList = gson.fromJson(jsonArray, new TypeToken<List<String>>() {}.getType());
Log.i("gson", "打印的结果是 strList.get(0)= " + strList.get(0) + " strList.get(1)=" + strList.get(1) + " strList.get(2)=" + strList.get(2)) ;
4。结果
打印的结果是 strList.get(0)= Swift strList.get(1)=Java strList.get(2)=PHP