内容简介:Gson可以结合泛型使用,但用到泛型时,需指定反序列化:
Gson.toJson(Object); Gson.fromJson(Reader,Class); Gson.fromJson(String,Class); Gson.fromJson(Reader,Type); Gson.fromJson(String,Type); 复制代码
2.基本数据类型解析
Gson可以结合泛型使用,但用到泛型时,需指定 type
,如 new TypeToken<List<String>>(){}.getType()
; TypeToken
的构造方法是protected的,所有这么写 new TypeToken<List<String>>(){}
Gson gson = new Gson();
反序列化:
int i = gson.fromJson("1",Integer.class); boolean b = gson.fromJson("\"true\"",Boolean.class); double d = gson.fromJson("1.1",Double.class); double d1 = gson.fromJson("\"1.2\"",Double.class); String str = gson.fromJson("TomCruise",String.class); List<String>stringList = gson.fromJson("[\"aa\",\"bb\"]",new TypeToken<List<String>>(){}.getType()); 复制代码
序列化:
String jsonInt = gson.toJson(2); String jsonBoolean = gson.toJson(false); // false String jsonString = gson.toJson("String"); //"String" List<String>list = new ArrayList<>(); list.add("a"); list.add("b"); String jsonList = gson.toJson(list); 复制代码
3.POJO类解析
POJO类:User
@JsonAdapter(UserTypeAdapter.class) public final class User { @Expose @Since(4) private String name; @Expose @Until(4) private int age; @Expose private Date date; @Expose private List<User>children; private User parent; // @SerializedName(value = "email_address",alternate = {"emailAddress","email"}) private String emailAddress; public User(String name, int age){ this.name = name; this.age = age; } ... ... } 复制代码
Gson自动化:
Gson gson = new Gson(); String json = "{\"name\":\"John\",\"age\":22,\"email_address\":\"xxx@163.com\"}"; User userF = gson.fromJson(json,User.class);//反序列化 User userT = new User("Tom",10); userT.setAddress("xxx"); String jsonUser = gson.toJson(userT);//序列化 复制代码
注:字符串中应注意使用转义字符,如 \"name\"
字段重命名:@SerializedName
Java中一般采用驼峰命名,如 emailAddress
,但后台有时命名方式不同,如 php 形式的 email_address
,此时 @SerializedName
注解就能起大作用。
@SerializedName
可以更改字段名,还能提供备用名属性: alternate
,使用如下:
@SerializedName(value = "email_address",alternate = {"emailAddress","email"}) 复制代码
当上面的三个属性(email_address、email、emailAddress)中出现任意一个时都能进行解析。
注:当多种情况同时出时,以最后一个出现的值为准。
4.泛型使用
Gson可以结合泛型使用,但用到泛型时,需指定 type
,如 new TypeToken<List<String>>(){}.getType()
; TypeToken
的构造方法是protected的,所有这么写 new TypeToken<List<String>>(){}
; 无论使用 List<User>
还是 List<String>
,最终都是 List.class
( 泛型擦除
)
引入泛型可以很大程度上方便接口的设计,如后台的返回数据格式常见两种:
{"code":"0","message":"success","data":{}}
和 {"code":"0","message":"success","data":[]
data的类型一种是对象,一种是数据,若无泛型的支持,则需定义两个httpResponse类,引入泛型,则只需定义一个泛型类,不用去写无谓的代码,能更专注于逻辑功能。
public final class HttpResult<T> { private int code; private boolean success; private T data; ... ... } 复制代码
使用时:
Gson gson = new Gson(); Type objType = new TypeToken<HttpResult<User>>(){}.getType(); Type listType = new TypeToken<HttpResult<List<User>>>(){}.getType(); HttpResult<User> objUser = gson.fromJson("{\"code\":200,\"data\":{\"age\":70,\"name\":\"Cap\"},\"success\":true}",objType); HttpResult<List<User>> listUser = gson.fromJson("{\"code\":200,\"data\":[{\"age\":70,\"name\":\"Cap\"}],\"success\":true}",listType); gson.toJson(objUser); gson.toJson(listUser); 复制代码
5、Null、日期格式化等Gson配置
Gson gson = new GsonBuilder() //格式化输出 .setPrettyPrinting() //序列化null .serializeNulls() // 设置日期时间格式,另有2个重载方法 // 在序列化和反序化时均生效 .setDateFormat("yyyy-MM-dd") // 禁此序列化内部类 .disableInnerClassSerialization() //生成不可执行的Json(多了 )]}' 这4个字符) .generateNonExecutableJson() //禁止转义html标签 .disableHtmlEscaping() .create(); User user = new User("John",30); user.setDate(new Date()); //日期格式化 Log.i("format",gson.toJson(user)); 复制代码
二、手动流式序列化和流式反序列化
利用 JsonReader
和 JsonWriter
手动读取
JsonReader
读取:
try { JsonReader jsonReader = new JsonReader(new StringReader("[{\"name\":\"Cap\",\"age\":70, \"address\":\"xxx@163.com\"}" + ",{\"name\":\"Thor\",\"age\":1000, \"address\":\"xxx@q.com\"}]")); jsonReader.beginArray(); while (jsonReader.hasNext()){ jsonReader.beginObject(); Log.d("JsonReaderArray",jsonReader.nextName()+":"+jsonReader.nextString()); Log.d("JsonReaderArray",jsonReader.nextName()+":"+jsonReader.nextInt()); Log.d("JsonReaderArray",jsonReader.nextName()+":"+jsonReader.nextString()); jsonReader.endObject(); } jsonReader.endArray(); }catch (Exception e){ e.printStackTrace(); } 复制代码
JsonWriter
读取:
try { StringWriter writer = new StringWriter(); JsonWriter jsonWriter = new JsonWriter(writer); jsonWriter.beginArray(); jsonWriter.beginObject(); jsonWriter.name("name") .value("Stark") .name("age") .value(50) .name("email") .value("xxx@qq.com"); jsonWriter.endObject(); jsonWriter.beginObject(); jsonWriter.name("name") .value("BlackWidow") .name("age") .value(40) .name("email") .value("xxx@qq.com"); jsonWriter.endObject(); jsonWriter.endArray(); jsonWriter.flush(); Log.i("JsonWriter","writer:"+writer.toString()); }catch (Exception e){ e.printStackTrace(); } 复制代码
注: beginObject和endObject配套使用,beginArray和endArray配套使用
三、过滤忽略字段
需要使用 new GsonBuilder()
配置
生成 Gson
对象。对于 Gson gson = new Gson()
直接生成的 Gson
对象 不起
作用。
1.@Expose注解
有两个属性值 deserialize
默认为true, serialize
默认为true。定义在字段上,表明是否在序列化或反序列化过程中暴露出来。
注:是 不导出的不加
@Expose @Expose(deserialize = true,serialize = true) //序列化和反序列化都都生效,等价于上一条 @Expose(deserialize = true,serialize = false) //反序列化时生效 @Expose(deserialize = false,serialize = true) //序列化时生效 @Expose(deserialize = false,serialize = false) // 和不写注解一样 复制代码
User配置如上文 POJO类:User 所示;
Gson gson = new GsonBuilder() .excludeFieldsWithoutExposeAnnotation()//Expose生效 // .serializeNulls() // .setPrettyPrinting() .create(); User user = new User("Tom",50); User child = new User("Kid",6); User parent = new User("parent",80); List<User> children = new ArrayList<>(); children.add(child); user.setChildren(children); user.setParent(parent); Log.d("expose","User:"+gson.toJson(user)); Log.i("expose","User:"+gson.fromJson("{\"age\":50,\"children\":[{\"age\":6,\"name\":\"Kid\"}],\"name\":\"Tom\",\"parent\":{\"age\":80,\"name\":\"parent\"}}" ,User.class)); 复制代码
2.版本号(@Since和@Until)
使用方法:当前版本(GsonBuilder中设置的版本) 大于等于Since的值时该字段导出,小于Until的值时该该字段导出。
User配置如上文 POJO类:User 所示;
Gson gson = new GsonBuilder() .setVersion(4) //设置版本号 .create(); User user = new User("Tom",50); User child = new User("Kid",6); User parent = new User("parent",80); List<User> children = new ArrayList<>(); children.add(child); user.setChildren(children); user.setParent(parent); Log.d("version","User:"+gson.toJson(user)); Log.i("version","User:"+gson.fromJson("{\"age\":50,\"children\":[{\"age\":6,\"name\":\"Kid\"}],\"name\":\"Tom\",\"parent\":{\"age\":80,\"name\":\"parent\"}}" ,User.class)); 复制代码
3.权限修饰符
即 public
static
final
private
protected
这些修饰符
使用方法:
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"; } 复制代码
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"} 复制代码
4.自定义过滤策略(最灵活方便)
基于 GsonBuilder
的 addSerializationExclusionStrategy
和 addDeserializationExclusionStrategy
,使用如下:
Gson gson = new GsonBuilder() .addSerializationExclusionStrategy(new ExclusionStrategy() { //基于字段排除 @Override public boolean shouldSkipField(FieldAttributes f) { // Expose expose = f.getAnnotation(Expose.class); // return expose!=null && !expose.serialize(); return false; } //基于类排除 @Override public boolean shouldSkipClass(Class<?> clazz) { return clazz == int.class||clazz== Integer.class; } }).create(); 复制代码
四、POJO与JSON字段名的映射规则
GsonBuilder
提供了 FieldNamingStrategy
接口和 setFieldNamingPolicy
和 setFieldNamingStrategy
两个方法,以及GSON的@SerializedName注解。
1.@SerializedName注解
注: @SerializedName注解拥有最高优先级 ,在加有@SerializedName注解的字段上FieldNamingStrategy不生效!
@SerializedName
可以更改字段名,还能提供备用名属性: alternate
,使用如下:
@SerializedName(value = "email_address",alternate = {"emailAddress","email"}) 复制代码
2.FieldNamingPolicy
结合 GsonBuilder.setFieldNamingPolicy
使用,对于:
User user = new User("Cap", 70); user.emailAddress = "xxx@163.com"; 复制代码
Gson gson = new GsonBuilder() .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE_WITH_SPACES) .create(); 复制代码
对应的字段效果是:
FieldNamingPolicy | 结果(仅输出emailAddress字段) |
---|---|
IDENTITY | {"emailAddress":"xxx@163.com"} |
LOWER_CASE_WITH_DASHES | {"email-address":"xxx@163.com"} |
LOWER_CASE_WITH_UNDERSCORES | {"email_address":"xxx@163.com"} |
UPPER_CAMEL_CASE | {"EmailAddress":"xxx@163.com"} |
UPPER_CAMEL_CASE_WITH_SPACES | {"Email Address":"xxx@163.com"} |
3.自定义实现
GsonBuilder.setFieldNamingStrategy
方法需要与Gson提供的 FieldNamingStrategy
接口配合使用,用于实现将POJO的字段与JSON的字段相对应。
注: FieldNamingPolicy
也实现了 FieldNamingStrategy
接口,即 FieldNamingPolicy
也可以使用 setFieldNamingStrategy
方法。
使用:
Gson gson = new GsonBuilder() .setFieldNamingStrategy(new FieldNamingStrategy() { @Override public String translateName(Field f) { //实现自己的规则 return null; } }) .create(); 复制代码
五、接管序列化和反序列化过程
使用 TypeAdapter
接口,或 JsonSerializer
、 JsonDeserializer
注: TypeAdapter
以及 JsonSerializer
和 JsonDeserializer
都需要与 GsonBuilder.registerTypeAdapter
或 GsonBuilder.registerTypeHierarchyAdapter
配合使用;
注:注册了 TypeAdapter之后,@SerializedName 、FieldNamingStrategy、Since、Until、Expose都失去了效果,直接由TypeAdapter之后接管。
registerTypeAdapter
与 registerTypeHierarchyAdapter
的区别:
registerTypeAdapter | registerTypeHierarchyAdapter | |
---|---|---|
支持泛型 | 是 | 否 |
支持继承 | 否 | 是 |
1.TypeAdapter
使用:
Gson gson =new GsonBuilder().registerTypeAdapter(User.class, new TypeAdapter<User>() { @Override public void write(JsonWriter out, User value) throws IOException { out.beginObject(); out.name("mName") .value(value.getName()); out.endObject(); out.flush(); } @Override public User read(JsonReader in) throws IOException { User user = new User("a",4); in.beginObject(); if (in.nextName().equals("mName")) user.setName(in.nextString()); in.endObject(); return user; } }).create(); User user = new User("我",10); Log.i("adapter","user:"+gson.toJson(user)); Log.i("adapter","user:"+gson.fromJson("{\"mName\":\"我\"}",User.class)); 复制代码
2.JsonSerializer和JsonDeserializer
TypeAdapter
接管了序列化和反序列化过程,而 JsonSerializer
和 JsonDeserializer
则只分别单独接管序列化和反序列化过程。
使用:
Gson gson =new GsonBuilder() .registerTypeAdapter(User.class, new JsonSerializer<User>() { @Override public JsonElement serialize(User src, Type typeOfSrc, JsonSerializationContext context) { JsonObject jsonElement = new JsonObject(); jsonElement.addProperty("name","serialize"); return jsonElement; } }) .registerTypeAdapter(User.class, new JsonDeserializer<User>() { @Override public User deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { User user = new User("",10); user.setName(json.getAsJsonObject().get("mName").getAsString()); return user; } }).create(); 复制代码
3.TypeAdapterFactory
用于创建 TypeAdapter
的工厂类,通过对比 Type
,确定有没有对应的 TypeAdapter
,没有就返回 null
,与 GsonBuilder.registerTypeAdapterFactory
配合使用。
Gson gson = new GsonBuilder() .registerTypeAdapterFactory(new TypeAdapterFactory() { @Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { return null; } }) .create(); 复制代码
4.@JsonAdapter注解
作用在 POJO类 上的,接收一个参数,且必须是TypeAdpater,JsonSerializer或JsonDeserializer这三个其中之一。
前面的 JsonSerializer
和 JsonDeserializer
都要配合 GsonBuilder.registerTypeAdapter
使用,但每次使用都要注册也太麻烦了, JsonAdapter
就是为了解决这个痛点的。
使用:
@JsonAdapter(UserTypeAdapter.class) public final class User { ..... } 复制代码
public class UserTypeAdapter implements JsonSerializer<User> { @Override public JsonElement serialize(User src, Type typeOfSrc, JsonSerializationContext context) { JsonObject jsonElement = new JsonObject(); jsonElement.addProperty("name","serialize"); return jsonElement; } } 复制代码
User user = new User("我",10); Log.i("adapter","user:"+new Gson().toJson(user));//直接使用简单的new GSON()即可,无需配置注册 复制代码
参考链接
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
python学习手册(原书第5版)
马克·卢茨 / 机械工业出版社 / 2018-10 / 219
如果你想动手编写高效、高质量并且很容易与其他语言和工具集成的代码,本书将快速地帮助你利用Python提高效率。本书基于Python专家的流程培训课程编写,内容通俗易懂。本书包含很多注释的例子和插图,以帮助你开始使用Python2.7和3.3。每章都包含关于Python语言的重要组成部分的一节课。本书主要内容:了解Python的主要内置对象类型,如数字、列表和字典;创建和处理对象的Python语句,......一起来看看 《python学习手册(原书第5版)》 这本书的介绍吧!