博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Gson使用总结
阅读量:6078 次
发布时间:2019-06-20

本文共 12966 字,大约阅读时间需要 43 分钟。

一、基础使用

1. 常用方法

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
stringList = gson.fromJson("[\"aa\",\"bb\"]",new TypeToken
>(){}.getType());复制代码

序列化:

String jsonInt = gson.toJson(2);String jsonBoolean = gson.toJson(false);    // falseString jsonString = gson.toJson("String"); //"String"List
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
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
{ private int code; private boolean success; private T data; ... ...}复制代码

使用时:

Gson gson = new Gson();Type objType = new TypeToken
>(){}.getType();Type listType = new TypeToken
>>(){}.getType(); HttpResult
objUser = gson.fromJson("{\"code\":200,\"data\":{\"age\":70,\"name\":\"Cap\"},\"success\":true}",objType);HttpResult
> 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));复制代码

二、手动流式序列化和流式反序列化

利用JsonReaderJsonWriter手动读取

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
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
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.自定义过滤策略(最灵活方便)

基于GsonBuilderaddSerializationExclusionStrategyaddDeserializationExclusionStrategy,使用如下:

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接口和setFieldNamingPolicysetFieldNamingStrategy两个方法,以及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接口,或JsonSerializerJsonDeserializer

TypeAdapter 以及 JsonSerializerJsonDeserializer 都需要与 GsonBuilder.registerTypeAdapterGsonBuilder.registerTypeHierarchyAdapter配合使用;

:注册了 TypeAdapter之后,@SerializedName 、FieldNamingStrategy、Since、Until、Expose都失去了效果,直接由TypeAdapter之后接管。

registerTypeAdapterregisterTypeHierarchyAdapter的区别:

registerTypeAdapter registerTypeHierarchyAdapter
支持泛型
支持继承

1.TypeAdapter

使用:

Gson gson  =new GsonBuilder().registerTypeAdapter(User.class, new TypeAdapter
() { @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接管了序列化和反序列化过程,而JsonSerializerJsonDeserializer则只分别单独接管序列化和反序列化过程。

使用:

Gson gson  =new GsonBuilder()        .registerTypeAdapter(User.class, new JsonSerializer
() { @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
() { @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 
TypeAdapter
create(Gson gson, TypeToken
type) { return null; } }) .create();复制代码

4.@JsonAdapter注解

作用在POJO类上的,接收一个参数,且必须是TypeAdpater,JsonSerializer或JsonDeserializer这三个其中之一。

前面的JsonSerializerJsonDeserializer都要配合GsonBuilder.registerTypeAdapter使用,但每次使用都要注册也太麻烦了,JsonAdapter就是为了解决这个痛点的。

使用:

@JsonAdapter(UserTypeAdapter.class)public final class User {    .....}复制代码
public class UserTypeAdapter implements JsonSerializer
{ @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()即可,无需配置注册复制代码

参考链接

转载地址:http://cuogx.baihongyu.com/

你可能感兴趣的文章
第三章 价值评估基础
查看>>
UML七种视图
查看>>
数据库与数据仓库的区别
查看>>
android项目数据库升级跨版本管理解决方案
查看>>
为什么要使用反射机制
查看>>
Day006
查看>>
jq ajax
查看>>
java环境变量设置方法
查看>>
tomcat配置使用log4j管理日志
查看>>
python学习day-2 字符串
查看>>
一个与我们软件的有关的小故事
查看>>
XPath 语法
查看>>
迁移数据之后,读取数据库变得很慢
查看>>
三行代码解决 winform 重绘闪烁,窗口重绘效率低下的问题
查看>>
go中利用hmset替换hset来提高redis的存取效率及并发goroutine可能遇到的问题
查看>>
谈iphone电话短信增强工具kuaidail软件的实现
查看>>
正则表达式-切割
查看>>
文艺青年会看这本《迷局》么?
查看>>
時間API用詞梳理
查看>>
小 X 与机器人 (betago)
查看>>