2024年最全Android Gson使用详解,爱奇艺算法社招面经

面试宝典

面试必问知识点、BATJ历年历年面试真题+解析

学习经验总结

(一)调整好心态
心态是一个人能否成功的关键,如果不调整好自己的心态,是很难静下心来学习的,尤其是现在这么浮躁的社会,大部分的程序员的现状就是三点一线,感觉很累,一些大龄的程序员更多的会感到焦虑,而且随着年龄的增长,这种焦虑感会越来越强烈,那么唯一的解决办法就是调整好自己的心态,要做到自信、年轻、勤奋。这样的调整,一方面对自己学习有帮助,另一方面让自己应对面试更从容,更顺利。

(二)时间挤一挤,制定好计划
一旦下定决心要提升自己,那么再忙的情况下也要每天挤一挤时间,切记不可“两天打渔三天晒网”。另外,制定好学习计划也是很有必要的,有逻辑有条理的复习,先查漏补缺,然后再系统复习,这样才能够做到事半功倍,效果才会立竿见影。

(三)不断学习技术知识,更新自己的知识储备
对于一名程序员来说,技术知识方面是非常重要的,可以说是重中之重。**要面试大厂,自己的知识储备一定要非常丰富,若缺胳膊少腿,别说在实际工作当中,光是面试这一关就过不了。**对于技术方面,首先基础知识一定要扎实,包括自己方向的语言基础、计算机基础、算法以及编程等等。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

Expose 注解的注解值声明情况有四种

@Expose(serialize = true, deserialize = true) //序列化和反序列化都生效
@Expose(serialize = false, deserialize = true) //序列化时不生效,反序列化时生效
@Expose(serialize = true, deserialize = false) //序列化时生效,反序列化时不生效
@Expose(serialize = false, deserialize = false) //序列化和反序列化都不生效,和不写注解一样

现在来看个例子,修改 User 类

/**

  • 作者:chenZY
  • 时间:2018/3/17 18:32
  • 描述:https://github.com/leavesC
    */
    public class User {

@Expose(serialize = true, deserialize = true) //序列化和反序列化都生效
private String a;

@Expose(serialize = false, deserialize = true) //序列化时不生效,反序列化时生效
private String b;

@Expose(serialize = true, deserialize = false) //序列化时生效,反序列化时不生效
private String c;

@Expose(serialize = false, deserialize = false) //序列化和反序列化都不生效,和不写注解一样
private String d;

private String e;

public User(String a, String b, String c, String d, String e) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.e = e;
}

@Override
public String toString() {
return “User{” +
“a='” + a + ‘’’ +
“, b='” + b + ‘’’ +
“, c='” + c + ‘’’ +
“, d='” + d + ‘’’ +
“, e='” + e + ‘’’ +
‘}’;
}

}

按照如上的注解值,只有声明了 Expose 注解且 serialize 值为 true 的字段才能被序列化,只有声明了 Expose 注解且 deserialize 值为 true 的字段才能被反序列化

public static void main(String[] args) {
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
User user = new User(“A”, “B”, “C”, “D”, “E”);
System.out.println();
System.out.println(gson.toJson(user));

String json = “{“a”:“A”,“b”:“B”,“c”:“C”,“d”:“D”,“e”:“E”}”;
user = gson.fromJson(json, User.class);
System.out.println();
System.out.println(user.toString());
}

3.2、基于版本

Gson 提供了 @Since 和 @Until 两个注解基于版本对字段进行过滤,@Since 和 @Until 都包含一个 Double 属性值,用于设置版本号。Since 的意思是“自……开始”,Until 的意思是“到……为止”,一样要和 GsonBuilder 配合使用。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface Since {
double value();
}

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface Until {
double value();
}

当版本( GsonBuilder 设置的版本) 大于或等于 Since 属性值或小于 Until 属性值时字段会进行序列化和反序列化操作,而没有声明注解的字段都会加入序列化和反序列操作

现在来看个例子,修改 User 类

/**

  • 作者:chenZY
  • 时间:2018/3/17 18:32
  • 描述:https://github.com/leavesC
    */
    public class User {

@Since(1.4)
private String a;

@Since(1.6)
private String b;

@Since(1.8)
private String c;

@Until(1.6)
private String d;

@Until(2.0)
private String e;

public User(String a, String b, String c, String d, String e) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.e = e;
}

@Override
public String toString() {
return “User{” +
“a='” + a + ‘’’ +
“, b='” + b + ‘’’ +
“, c='” + c + ‘’’ +
“, d='” + d + ‘’’ +
“, e='” + e + ‘’’ +
‘}’;
}

}

public static void main(String[] args) {
Gson gson = new GsonBuilder().setVersion(1.6).create();
User user = new User(“A”, “B”, “C”, “D”, “E”);
System.out.println();
System.out.println(gson.toJson(user));

String json = “{“a”:“A”,“b”:“B”,“c”:“C”,“d”:“D”,“e”:“E”}”;
user = gson.fromJson(json, User.class);
System.out.println();
System.out.println(user.toString());
}

3.3、基于访问修饰符

访问修饰符由 java.lang.reflect.Modifier 提供 int 类型的定义,而 GsonBuilder 对象的 excludeFieldsWithModifiers方法接收一个 int 类型可变参数,指定不进行序列化和反序列化操作的访问修饰符字段 看个例子

/**

  • 作者:chenZY
  • 时间:2018/3/17 18:32
  • 描述:https://github.com/leavesC
    */
    public class ModifierSample {

public String publicField = “public”;

protected String protectedField = “protected”;

private String privateField = “private”;

String defaultField = “default”;

final String finalField = “final”;

static String staticField = “static”;

}

public static void main(String[] args) {
Gson gson = new GsonBuilder().excludeFieldsWithModifiers(Modifier.PRIVATE, Modifier.STATIC).create();
ModifierSample modifierSample = new ModifierSample();
System.out.println(gson.toJson(modifierSample));
}

3.4、基于策略

GsonBuilder 类包含 setExclusionStrategies(ExclusionStrategy... strategies)方法用于传入不定长参数的策略方法,用于直接排除指定字段名或者指定字段类型 看个例子

/**

  • 作者:chenZY
  • 时间:2018/3/17 18:32
  • 描述:https://github.com/leavesC
    */
    public class Strategies {

private String stringField;

private int intField;

private double doubleField;

public Strategies(String stringField, int intField, double doubleField) {
this.stringField = stringField;
this.intField = intField;
this.doubleField = doubleField;
}

@Override
public String toString() {
return “Strategies{” +
“stringField='” + stringField + ‘’’ +
“, intField=” + intField +
“, doubleField=” + doubleField +
‘}’;
}

}

public static void main(String[] args) {
Gson gson = new GsonBuilder().setExclusionStrategies(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes fieldAttributes) {
//排除指定字段名
return fieldAttributes.getName().equals(“intField”);
}

@Override
public boolean shouldSkipClass(Class<?> aClass) {
//排除指定字段类型
return aClass.getName().equals(double.class.getName());
}
}).create();

Strategies strategies = new Strategies(“stringField”, 111, 11.22);
System.out.println();
System.out.println(gson.toJson(strategies));

String json = “{“stringField”:“stringField”,“intField”:111,“doubleField”:11.22}”;
strategies = gson.fromJson(json, Strategies.class);
System.out.println();
System.out.println(strategies);
}

字段名为 “intField” 和字段类型为 double 的字段都会被排除掉

setExclusionStrategies 方法在序列化和反序列化时都会生效,如果只是想指定其中一种情况下的排除策略或分别指定排除策略,可以改为使用以下两个方法

addSerializationExclusionStrategy(ExclusionStrategy strategy);

addDeserializationExclusionStrategy(ExclusionStrategy strategy);

四、个性化配置

4.1、输出 null

对于 Gson 而言,在序列化时如果某个属性值为 null 的话,那么在序列化时该字段不会参与进来,如果想要显示输出该字段的话,可以通过 GsonBuilder 进行配置

/**

  • 作者:chenZY
  • 时间:2018/3/17 18:32
  • 描述:https://github.com/leavesC
    */
    public class Strategies {

private String stringField;

private int intField;

private double doubleField;

}

public static void main(String[] args) {
Gson gson = new GsonBuilder()
.serializeNulls() //输出null
.create();
Strategies strategies = new Strategies(null, 24, 22.333);
System.out.println();
System.out.println(gson.toJson(strategies));
}

4.2、格式化输出Json

默认的序列化后的 Josn 字符串并不太直观,可以选择格式化输出

public static void main(String[] args) {
Gson gson = new GsonBuilder()
.serializeNulls() //输出null
.setPrettyPrinting()//格式化输出
.create();
Strategies strategies = new Strategies(null, 24, 22.333);
System.out.println();
System.out.println(gson.toJson(strategies));
}

4.3、格式化时间

Gson 也可以对时间值进行格式化

/**

  • 作者:chenZY
  • 时间:2018/3/17 18:32
  • 描述:https://github.com/leavesC
    */
    public class Strategies {

private Date date;

private Date date2;

public Strategies(Date date, Date date2) {
this.date = date;
this.date2 = date2;
}

@Override
public String toString() {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss:SSS”, Locale.CHINA);
return “Strategies{” +
“date=” + simpleDateFormat.format(date) +
“, date2=” + simpleDateFormat.format(date2) +
‘}’;
}

}

public static void main(String[] args) {
Gson gson = new GsonBuilder()
.setPrettyPrinting()//格式化输出
.setDateFormat(“yyyy-MM-dd HH:mm:ss:SSS”)//格式
化时间
.create();
Date date = new Date();
Strategies strategies = new Strategies(date, new Date(date.getTime() + 1000000));
System.out.println();
System.out.println(gson.toJson(strategies));

String json = “{\n” +
" “date”: “2018-03-17 19:38:50:033”,\n" +
" “date2”: “2018-03-17 19:55:30:033”\n" +
“}”;
System.out.println();
System.out.println(gson.fromJson(json, Strategies.class));
}

五、TypeAdapter

TypeAdapter 是一个泛型抽象类,用于接管某种类型的序列化和反序列化过程,包含两个抽象方法,分别用于自定义序列化和反序列化过程

public abstract void write(JsonWriter var1, T var2) throws IOException;

public abstract T read(JsonReader var1) throws IOException;

下面看个简单的例子

/**

  • 作者:chenZY
  • 时间:2018/3/17 18:32
  • 描述:https://github.com/leavesC
    */
    public class User {

private String name;

private int age;

private boolean sex;

public User() {
}

public User(String name, int age, boolean sex) {
this.name = name;
this.age = age;
this.sex = sex;
}

@Override
public String toString() {
return “User{” +
“name='” + name + ‘’’ +
“, age=” + age +
“, sex=” + sex +
‘}’;
}

}

定义 TypeAdapter 的子类 UserTypeAdapter 来接管 User 类的序列化和反序列化过程 这里设定当 User 类序列化时 Json 中的Key值都是大写字母开头,反序列化时支持“name”和“Name”两种不同的 Json 风格

public class UserTypeAdapter extends TypeAdapter {

@Override
public void write(JsonWriter jsonWriter, User user) throws IOException {
//流式序列化成对象开始
jsonWriter.beginObject();
//将Json的Key值都指定为大写字母开头
jsonWriter.name(“Name”).value(user.getName());
jsonWriter.name(“Age”).value(user.getAge());
jsonWriter.name(“Sex”).value(user.isSex());
//流式序列化结束
jsonWriter.endObject();
}

@Override
public User read(JsonReader jsonReader) throws IOException {
User user = new User();
//流式反序列化开始
jsonReader.beginObject();
while (jsonReader.hasNext()) {
switch (jsonReader.nextName()) {
//首字母大小写均合法
case “name”:
case “Name”:
user.setName(jsonReader.nextString());
break;
case “age”:
user.setAge(jsonReader.nextInt());
break;
case “sex”:
user.setSex(jsonReader.nextBoolean());
break;
}

}
//流式反序列化结束
jsonReader.endObject();
return user;
}

}

public static void main(String[] args) {
Gson gson = new GsonBuilder().registerTypeAdapter(User.class, new UserTypeAdapter()).create();
User user = new User(“leavesC”, 24, true);
System.out.println();
System.out.println(gson.toJson(user));

String json = “{“Name”:“leavesC”,“age”:24,“sex”:true}”;
user = gson.fromJson(json, User.class);
System.out.println();
System.out.println(user);
}

可以看到 User 类按照预定义的策略来完成序列化和反序列化了

六、JsonSerializer 和 JsonDeserializer

TypeAdapter 将序列化和反序列操作都接管了过来,其实 Gson 还提供了只接管序列化过程的接口,即 JsonSerializer 看个例子

public static void main(String[] args) {
Gson gson = new GsonBuilder().registerTypeAdapter(User.class, new JsonSerializer() {
@Override
public JsonElement serialize(User user, Type type, JsonSerializationContext jsonSerializationContext) {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty(“NameHi”, user.getName());
jsonObject.addProperty(“Sex”, user.isSex());
jsonObject.addProperty(“Age”, user.getAge());
return jsonObject;
}
}).create();
User user = new User(“leavesC”, 24, true);
System.out.println();
System.out.println(gson.toJson(user));
}

相对应的,JsonDeserializer 接口提供了反序列化的接口

public static void main(String[] args) {
Gson gson = new GsonBuilder().registerTypeAdapter(User.class, new JsonDeserializer() {
@Override
public User deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
JsonObject jsonObject = jsonElement.getAsJsonObject();
String name = null;
//同时支持 userName 和 name 两种情况
if (jsonObject.has(“userName”)) {
name = jsonObject.get(“userName”).getAsString();
} else if (jsonObject.has(“name”)) {
name = jsonObject.get(“name”).getAsString();
}
int age = jsonObject.get(“age”).getAsInt();
boolean sex = jsonObject.get(“sex”).getAsBoolean();
return new User(name, age, sex);
}
}).create();
String json = “{“userName”:“leavesC”,“sex”:true,“age”:24}”;
User user = gson.fromJson(json, User.class);
System.out.println();
System.out.println(user);

json = “{“name”:“leavesC”,“sex”:true,“age”:24}”;
user = gson.fromJson(json, User.class);
System.out.println();
System.out.println(user);
}

这里有个比较麻烦的地方,那就是在使用 TypeAdapter 、JsonSerializerJsonDeserializer 时,总需要调用 registerTypeAdapter 方法进行注册,那有没有更简单的注册方法呢? 有的,Gosn 还提供了另一个注解 @JsonAdapter 用于进行简单的声明

类似于这样,声明了 User 类的序列化或反序列化操作由 UserTypeAdapter 完成,注解的优先级高于 registerTypeAdapter 方法

最后

这里我希望可以帮助到大家提升进阶。

内容包含:Android学习PDF+架构视频+面试文档+源码笔记高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 这几块的内容。非常适合近期有面试和想在技术道路上继续精进的朋友。

喜欢本文的话,不妨给我点个小赞、评论区留言或者转发支持一下呗~

img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

这里我希望可以帮助到大家提升进阶。

内容包含:Android学习PDF+架构视频+面试文档+源码笔记高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 这几块的内容。非常适合近期有面试和想在技术道路上继续精进的朋友。

喜欢本文的话,不妨给我点个小赞、评论区留言或者转发支持一下呗~

img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值