Android-Gson使用详解
Gson的基本用法
Gson解析默认使用方法很简单,将json转换成对象用Gson.fromJson(),将对象转化成json用Gson.toJson()即可。Gson解析解析数组和List也是用相同的方法。当解析List的时候,可能会遇到泛型操作。此时需要使用TypeToken对象来实现泛型支持。
public static void main(String[] args){
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
String jsonNumber = gson.toJson(100f); // 100
String jsonBoolean = gson.toJson(false); // false
String jsonString = gson.toJson("String"); //"String"
//解析自定义类型
User user = new User("怪盗kidou",24);
String jsonObject = gson.toJson(user); // {"name":"怪盗kidou","age":24}
String jsonStringObj = "{\"name\":\"怪盗kidou\",\"age\":24}";
User userObj = gson.fromJson(jsonString, User.class);
//解析数组和List列表
String json = "[\"Android\",\"Java\",\"PHP\"]";
String[] strings = gson.fromJson(json, String[].class);
List<String> stringList = gson.fromJson(json, new TypeToken<List<String>>() {}.getType());
}
public static class User {
public String name;
public int age;
public User(String name, int age){
this.name = name;
this.age = age;
}
}
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
String jsonNumber = gson.toJson(100f); // 100
String jsonBoolean = gson.toJson(false); // false
String jsonString = gson.toJson("String"); //"String"
//解析自定义类型
User user = new User("怪盗kidou",24);
String jsonObject = gson.toJson(user); // {"name":"怪盗kidou","age":24}
String jsonStringObj = "{\"name\":\"怪盗kidou\",\"age\":24}";
User userObj = gson.fromJson(jsonString, User.class);
//解析数组和List列表
String json = "[\"Android\",\"Java\",\"PHP\"]";
String[] strings = gson.fromJson(json, String[].class);
List<String> stringList = gson.fromJson(json, new TypeToken<List<String>>() {}.getType());
}
public static class User {
public String name;
public int age;
public User(String name, int age){
this.name = name;
this.age = age;
}
}
属性重命名 @SerializedName 注解
Gson通过@SerializedName 注解提供备选属性名,@SerializedName注解提供了两个属性,value和alternate。
- alternate:接收一个String数组,数组中的String都为备选属性名
- value:接收一个String对象,作为默认映射的json属性名。添加此属性,将导致java对象属性名的默认映射无效
public static void main(String[] args){
Gson gson = new Gson();
String jsonString = "{\"name\":\"怪盗kidou\",\"age\":24,\"emailAddress\":\"[email protected]\"}";
User userObj = gson.fromJson(jsonString, User.class);
jsonString = "{\"name\":\"怪盗kidou\",\"age\":24,\"email_address\":\"[email protected]\"}";
userObj = gson.fromJson(jsonString, User.class);
jsonString = "{\"name\":\"怪盗kidou\",\"age\":24,\"email\":\"[email protected]\"}";
userObj = gson.fromJson(jsonString, User.class);
}
public static class User {
@SerializedName(value = "emailAddress", alternate = {"email", "email_address"})
public String emailAddress;
public String name;
public int age;
}
Gson gson = new Gson();
String jsonString = "{\"name\":\"怪盗kidou\",\"age\":24,\"emailAddress\":\"[email protected]\"}";
User userObj = gson.fromJson(jsonString, User.class);
jsonString = "{\"name\":\"怪盗kidou\",\"age\":24,\"email_address\":\"[email protected]\"}";
userObj = gson.fromJson(jsonString, User.class);
jsonString = "{\"name\":\"怪盗kidou\",\"age\":24,\"email\":\"[email protected]\"}";
userObj = gson.fromJson(jsonString, User.class);
}
public static class User {
@SerializedName(value = "emailAddress", alternate = {"email", "email_address"})
public String emailAddress;
public String name;
public int age;
}
Gson支持泛型
Java中List<String> 和List<User> 在编译后,都是同一个类,即List.class,这是Java泛型使用时的泛型擦除。而Gson是使用反射来编译对象的 ,所以Gson要支持泛型转化,需要通过TypeToken类的帮助。泛型反序列化List<String>需要通过以下方式:
Gson.fromJson(jsonArray, new TypeToken<List<String>>() {}.getType());
使用示例如下:
public static void main(String arg[]){
Gson gson = new Gson();
String json = "{\"code\":\"0\",\"message\":\"success\",\"data\":{\"name\":\"daiyibo\", \"age\":15}}";
Result<User> object = gson.fromJson(json, new TypeToken<Result<User>>() {}.getType());
json = "{\"code\":\"0\",\"message\":\"success\",\"data\":[{\"name\":\"daiyibo\", \"age\":15}, {\"name\":\"android\", \"age\":15}]}";
Result<List<User>> list = gson.fromJson(json, new TypeToken<Result<List<User>>>() {}.getType());
System.out.print(list.toString());
}
public static class Result<T> {
public int code;
public String message;
public T data;
}
public static class User{
public String name;
public int age;
}
Gson gson = new Gson();
String json = "{\"code\":\"0\",\"message\":\"success\",\"data\":{\"name\":\"daiyibo\", \"age\":15}}";
Result<User> object = gson.fromJson(json, new TypeToken<Result<User>>() {}.getType());
json = "{\"code\":\"0\",\"message\":\"success\",\"data\":[{\"name\":\"daiyibo\", \"age\":15}, {\"name\":\"android\", \"age\":15}]}";
Result<List<User>> list = gson.fromJson(json, new TypeToken<Result<List<User>>>() {}.getType());
System.out.print(list.toString());
}
public static class Result<T> {
public int code;
public String message;
public T data;
}
public static class User{
public String name;
public int age;
}
流方式反序列化
流式反序列化,主要通过stream包下的JsonReader类来手动实现反序列化;流式序列化,主要通过stream包下JsonWriter类来实现序列化。
public static void main(String[] args) throws Exception{ // 流式反序列化 String json = "{\"name\":\"怪盗kidou\",\"age\":\"24\"}"; User user = new User(); JsonReader reader = new JsonReader(new StringReader(json)); reader.beginObject(); // throws IOException while (reader.hasNext()) { String s = reader.nextName(); switch (s) { case "name": user.name = reader.nextString(); break; case "age": user.age = reader.nextInt(); //自动转换 break; case "email": user.email = reader.nextString(); break; } } reader.endObject(); System.out.println(user); // 流式序列化 JsonWriter writer = new JsonWriter(new OutputStreamWriter(System.out)); writer.beginObject() // throws IOException .name("name").value("怪盗kidou") .name("age").value(24) .name("email").nullValue() //演示null .endObject(); // throws IOException writer.flush(); // throws IOException //{"name":"怪盗kidou","age":24,"email":null} } public static class User { public String email; public String name; public int age; }
GsonBuilder构造自定义Gson
一般情况下Gson类提供的 API已经能满足大部分的使用场景,但我们需要更多更特殊、更强大的功能时,就需要对Gson进行特殊设置。GsonBuilder用于构建Gson实例的构造器,要改变Gson默认的设置必须使用该类配置Gson。常用配置如下:
Gson gson = new GsonBuilder() //序列化null .serializeNulls() // 设置日期时间格式,另有2个重载方法 // 在序列化和反序化时均生效 .setDateFormat("yyyy-MM-dd") // 禁此序列化内部类 .disableInnerClassSerialization() //生成不可执行的Json(多了 )]}' 这4个字符) .generateNonExecutableJson() //禁止转义html标签 .disableHtmlEscaping() //格式化输出 .setPrettyPrinting() .create();
序列化暴露属性@Expose注解
默认Gson对象,不对@Expose注解进行处理。所以在普通new Gson()对象中,@Expose注解无效。@Expose注解是用于处理暴露字段的,该注解必须和GsonBuilder配合使用。需要注意的是,属性中添加@Expose注解表示需要被序列化,否则默认为不对其进行序列化。
@Expose注解提供了两个属性,deserialize和serialize。
- deserialize:true表示反序列化生效,false表示反序列化不生效,默认为true
- serialize:true表示序列化生效,false表示序列化不生效,默认为true
public static void main(String[] args) throws Exception{ Gson gson = new GsonBuilder() .excludeFieldsWithoutExposeAnnotation() .create(); User user = new User(); user.name = "daiyibo"; user.age = 15; gson.toJson(user); } public static class User { //等价于@Expose(deserialize = false,serialize = false) public int age; @Expose public String name; }
Gson控制版本
Gson在对基于版本的字段提供了两个注解 @Since 和 @Until,和GsonBuilder.setVersion(Double)配合使用。@Since 和 @Until都接收一个Double值。
- @Since:当前版本(GsonBuilder中设置的版本)大于等于Since的值时该字段导出
- @Until:当前版本(GsonBuilder中设置的版本)小于Until的值时该该字段导出
public static void main(String[] args) throws Exception{ SinceUntilSample sinceUntilSample = new SinceUntilSample(); sinceUntilSample.since = "since"; sinceUntilSample.until = "until"; Gson gson = new GsonBuilder().setVersion(5).create(); System.out.println(gson.toJson(sinceUntilSample)); //当version <4时,结果:{"until":"until"} //当version >=4 && version <5时,结果:{"since":"since","until":"until"} //当version >=5时,结果:{"since":"since"} } public static class SinceUntilSample { @Since(4) public String since; @Until(5) public String until; }
Gson控制访问修饰符
通过对类中的属性,修饰不同的修饰符,例如public、static 、final、private、protected。然后,使用GsonBuilder.excludeFieldsWithModifiers()构建gson,设置过滤的修饰符属性(java.lang.reflect.Modifier类中获取)
public static void main(String[] args) throws Exception{ ModifierSample modifierSample = new ModifierSample(); Gson gson = new GsonBuilder() .excludeFieldsWithModifiers(Modifier.FINAL, Modifier.STATIC, Modifier.PRIVATE) .create(); System.out.println(gson.toJson(modifierSample)); // 结果:{"publicField":"public","protectedField":"protected","defaultField":"default"} } public static class ModifierSample { final String finalField = "final"; static String staticField = "static"; public String publicField = "public"; protected String protectedField = "protected"; String defaultField = "default"; private String privateField = "private"; }
Gson基于策略过滤字段
通过设置GsonBuilder中的addSerializationExclusionStrategy()设置序列化和addDeserializationExclusionStrategy()设置反序化。这两个方法的参数为Gson的ExclusionStrategy接口,主要用于描述在序列化(反序列化)时,被过滤的字段和类。
ExclusionStrategy方法介绍
- public boolean shouldSkipField(FieldAttributes f);//决定是否排除该字段,return true为排除
- public boolean shouldSkipClass(Class<?> clazz);//是否排除类,return true为排除
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();
GsonBuilder属性重命名
直接通过GsonBuilder设置属性重命名,有两个方式setFieldNamingPolicy()和setFieldNamingStrategy()。setFieldNamingPolicy()相当于的setFieldNamingStrategy()方法的子集,并且Gson总结了经常使用的情况的枚举类FieldNamingPolicy。注意点:@SerializedName注解拥有最高优先级,在加有@SerializedName注解的字段上FieldNamingStrategy不生效!
setFieldNamingPolicy使用介绍
public static void main(String[] args) throws Exception{ Gson gson = new GsonBuilder() .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE) .create(); String json = gson.toJson(new User()); System.out.println(json); } public static class User { private String userinfo = "userinfo"; private String userInfo = "userInfo"; }
枚举类型作用介绍
IDENTITY | {"emailAddress":"[email protected]"} |
LOWER_CASE_WITH_DASHES | {"email-address":"[email protected]"} |
LOWER_CASE_WITH_UNDERSCORES | {"email_address":"[email protected]"} |
UPPER_CAMEL_CASE | {"EmailAddress":"[email protected]"} |
UPPER_CAMEL_CASE_WITH_SPACES | {"Email Address":"[email protected]"} |
setFieldNamingStrategy使用介绍
public static void main(String[] args) throws Exception{ Gson gson = new GsonBuilder() .setFieldNamingStrategy(new FieldNamingStrategy() { @Override public String translateName(Field f) { //实现自己的规则 if ("userInfo".equals(f.getName())){ return "u_s_e_r_i_n_f_o"; } return f.getName(); } }) .create(); String json = gson.toJson(new User()); System.out.println(json); } public static class User { private String userInfo = "userInfo"; }
TypeAdapter,JsonSerializer,JsonDeserializer介绍
TypeAdapter,JsonSerializer,JsonDeserializer三个类的简单描述
- TypeAdapter,抽象类形式,主要用来接管某种类型的序列化和反序列化过程,主要包含两个方法write(JsonWriter,T) 和 read(JsonReader)
- JsonSerializer,为接口形式,主要用来接管序列化的过程
- JsonDeserializer,为接口形式,主要用来接管反序列化的过程
Gson.registerTypeAdapter()与Gson.registerTypeHierarchyAdapter()两个方法来注册TypeAdapter,JsonSerializer,JsonDeserializer适配单元。
- Gson.registerTypeAdapter(),主要用来注册类,不支持继承。即,注册Number.class时,Integer.class也不生效。
- Gson.registerTypeHierarchyAdapter(),主要用来注册类,支持继承。即,注册Number.class时,Integer.class也生效。
public static void main(String[] args) throws Exception { User user = new User(); user.name = "怪盗kidou"; user.age = 24; user.email = "[email protected]"; Gson gson = new GsonBuilder() .registerTypeAdapter(User.class, new UserTypeAdapter())//为User注册TypeAdapter .create(); // 序列化 String json = gson.toJson(user); System.out.println(json);//out: {"name":"怪盗kidou","age":24,"email":"[email protected]"} // 反序列化 json = "{\"name\":\"怪盗kidou\",\"age\":24,\"email\":\"[email protected]\"}"; user = gson.fromJson(json, User.class); System.out.println(user);//out: name:怪盗kidou age:24 email:[email protected] json = "{\"name\":\"怪盗kidou\",\"age\":24,\"email_address\":\"[email protected]\"}"; user = gson.fromJson(json, User.class); System.out.println(user);//out: name:怪盗kidou age:24 email:[email protected] json = "{\"name\":\"怪盗kidou\",\"age\":24,\"emailAddress\":\"[email protected]\"}"; user = gson.fromJson(json, User.class); System.out.println(user);//out: name:怪盗kidou age:24 email:[email protected] // JsonDeserializer与JsonSerializer使用介绍 gson = new GsonBuilder() .registerTypeAdapter(Integer.class, new IntegerJsonDeserializer()) .registerTypeAdapter(Integer.class, new IntegerJsonSerializer()) .create(); System.out.println(gson.toJson(100));//out: "number:100" System.out.println(gson.fromJson("\"\"", Integer.class));//out: -1 } public static class UserTypeAdapter extends TypeAdapter<User> { @Override public void write(JsonWriter out, User value) throws IOException { out.beginObject(); out.name("name").value(value.name); out.name("age").value(value.age); out.name("email").value(value.email); out.endObject(); } @Override public User read(JsonReader in) throws IOException { User user = new User(); in.beginObject(); while (in.hasNext()) { switch (in.nextName()) { case "name": user.name = in.nextString(); break; case "age": user.age = in.nextInt(); break; case "email": case "email_address": case "emailAddress": user.email = in.nextString(); break; } } in.endObject(); return user; } } public static class IntegerJsonDeserializer implements JsonDeserializer<java.lang.Integer> { public java.lang.Integer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { try { return json.getAsInt(); } catch (NumberFormatException e) { return -1; } } } public static class IntegerJsonSerializer implements JsonSerializer<java.lang.Integer> { public JsonElement serialize(Integer src, Type typeOfSrc, JsonSerializationContext context){ return new JsonPrimitive("number:" + String.valueOf(src)); } } public static class User{ private String name; private int age; private String email; public String toString(){ return "name:" + name + " age:" + age + " email:" + email; } }
TypeAdapterFactory
TypeAdapterFactory用于创建TypeAdapter的工厂类,通过对比Type,确定有没有对应的TypeAdapter,没有就返回null,与GsonBuilder.registerTypeAdapterFactory配合使用。使用示范如下:
public static void main(String[] args) throws Exception { Gson gson = new GsonBuilder() .registerTypeAdapterFactory(new TypeAdapterFactory() { @Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { if (type.equals(new TypeToken<User>() {}.getType())){ return (TypeAdapter<T>) new UserTypeAdapter(); } return null; } }) .create(); // 序列化 User user = new User(); user.name = "daiyibo"; user.age = 24; user.email = "[email protected]"; System.out.println(gson.toJson(user));//out: {"name":"daiyibo","age":24,"email":"[email protected]"} user = gson.fromJson("{\"name\":\"daiyibo\",\"age\":24,\"email_address\":\"[email protected]\"}", User.class); System.out.println(user.toString());//out: {"name":"daiyibo","age":24,"email":"[email protected]"} } public static class UserTypeAdapter extends TypeAdapter<User> { @Override public void write(JsonWriter out, User value) throws IOException { out.beginObject(); out.name("name").value(value.name); out.name("age").value(value.age); out.name("email").value(value.email); out.endObject(); } @Override public User read(JsonReader in) throws IOException { User user = new User(); in.beginObject(); while (in.hasNext()) { switch (in.nextName()) { case "name": user.name = in.nextString(); break; case "age": user.age = in.nextInt(); break; case "email": case "email_address": case "emailAddress": user.email = in.nextString(); break; } } in.endObject(); return user; } } public static class User{ private String name; private int age; private String email; public String toString(){ return "name:" + name + " age:" + age + " email:" + email; } }
@JsonAdapter注解
@JsonAdapter是用在类上的注解,接收一个参数,且必须是TypeAdpater,JsonSerializer或JsonDeserializer这三个其中之一,用来定义该类的序列化方法。注意点:@JsonAdapter的优先级比GsonBuilder.registerTypeAdapter的优先级更高。使用方法如下:
public static void main(String[] args) throws Exception { Gson gson = new Gson(); User user = new User(); user.name = "daiyibo"; user.age = 24; user.email = "[email protected]"; System.out.println(gson.toJson(user));//out: {"name":"daiyibo","age":24,"email":"[email protected]"} user = gson.fromJson("{\"name\":\"daiyibo\",\"age\":24,\"email_address\":\"[email protected]\"}", User.class); System.out.println(user.toString());//out: {"name":"daiyibo","age":24,"email":"[email protected]"} } @JsonAdapter(UserTypeAdapter.class) public static class User{ private String name; private int age; private String email; public String toString(){ return "name:" + name + " age:" + age + " email:" + email; } } public static class UserTypeAdapter extends TypeAdapter<User> { @Override public void write(JsonWriter out, User value) throws IOException { out.beginObject(); out.name("name").value(value.name); out.name("age").value(value.age); out.name("email").value(value.email); out.endObject(); } @Override public User read(JsonReader in) throws IOException { User user = new User(); in.beginObject(); while (in.hasNext()) { switch (in.nextName()) { case "name": user.name = in.nextString(); break; case "age": user.age = in.nextInt(); break; case "email": case "email_address": case "emailAddress": user.email = in.nextString(); break; } } in.endObject(); return user; } }
Gson源码UML类图
Gson解析流程图
Gson如何解决泛型问题
Gson反序列化泛型时,使用如下方式:
Type collectionType = new TypeToken<Collection<Integer>>(){}.getType(); Collection<Integer> ints2 = gson.fromJson(json, collectionType);
这里生成了TypeToken的匿名类来实现泛型标记,在TypeToken构造函数中,会生成type对象(getType()返回值)。type实际赋值语句如下:
//实际内容:com.google.gson.reflect.TypeToken<MainTest.MainTest$Result<MainTest$User>> Type superclass = subclass.getGenericSuperclass(); //实际内容:MainTest.MainTest$Result<MainTest$User> return ((ParameterizedType) superclass).getActualTypeArguments()[0];
参考
官方文档: