Gson使用总结

栏目: 服务器 · 发布时间: 6年前

内容简介: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));
复制代码

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

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

基于 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<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 接管了序列化和反序列化过程,而 JsonSerializerJsonDeserializer 则只分别单独接管序列化和反序列化过程。

使用:

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这三个其中之一。

前面的 JsonSerializerJsonDeserializer 都要配合 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()即可,无需配置注册
复制代码

参考链接

  1. Github UserGuide
  2. 怪盗kidou Gson系列文章

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Python for Everyone

Python for Everyone

Cay S. Horstmann、Rance D. Necaise / John Wiley & Sons / 2013-4-26 / GBP 181.99

Cay Horstmann's" Python for Everyone "provides readers with step-by-step guidance, a feature that is immensely helpful for building confidence and providing an outline for the task at hand. "Problem S......一起来看看 《Python for Everyone》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具