Gson:GitHub 标星 18K 的 JSON 解析器,Google 出品的 Java JSON 解析器

HarmonyOS学习 2021-11-25 18:26:04
java 面试 编程语言 后端开发

测试用例我已经帮你写好了,放在 GitHub 上,如果你不相信的话,可以验证一下。

 https://github.com/google/gson/blob/master/gson/src/test/java/com/google/gson/metrics/PerformanceTest.java

 04、使用指南

不是我自吹自擂,是真的,我还是挺好用的,上手难度几乎为零。如果你不相信话,可以来试试。

我有一个女朋友,她的名字和我一样,也叫 Gson,我的主要功能都由她来提供。你可以通过 new Gson() 的这种简单粗暴的方式创建她,也可以打电话给一个叫 GsonBuilder 的老板,让他邮寄一个复刻版过来,真的,我不骗你。

先来看一个序列化的例子。

Gson gson = new Gson();

System.out.println(gson.toJson(18));

System.out.println(gson.toJson(“沉默”));

System.out.println(gson.toJson(new Integer(18)));

int[] values = { 18,20 };

System.out.println(gson.toJson(values));

在我女朋友的帮助下,你可以将基本数据类型 int、字符串类型 String、包装器类型 Intege

《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》

【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享

r、int 数组等等作为参数,传递给 toJson() 方法,该方法将会返回一个 JSON 形式的字符串。

来看一下输出结果:

18

“沉默”

18

[18,20]

再来看一下反序列化的例子。

Gson gson = new Gson();

int one = gson.fromJson(“1”, int.class);

Integer two = gson.fromJson(“2”, Integer.class);

Boolean false1 = gson.fromJson(“false”, Boolean.class);

String str = gson.fromJson(““王二””, String.class);

String[] anotherStr = gson.fromJson(“[“沉默”,“王二”]”, String[].class);

System.out.println(one);

System.out.println(two);

System.out.println(false1);

System.out.println(str);

System.out.println(Arrays.toString(anotherStr));

toJson() 方法用于序列化,对应的,fromJson() 方法用于反序列化。不过,你需要在反序列化的时候,指定参数的类型,是 int 还是 Integer,是 Boolean 还是 String,或者 String 数组。

来看一下输出结果:

1

2

false

王二

[沉默, 王二]

上面的例子都比较简单,还体现不出来我的威力。

下面,我们来自定义一个类:

public class Writer {

private int age = 18;

private String name = “王二”;

private transient int sex = 1;

}

然后,我们来将其序列化:

Writer writer = new Writer();

Gson gson = new Gson();

String json = gson.toJson(writer);

System.out.println(json);

用法和之前一样简单,来看一下输出结果:

{“age”:18,“name”:“王二”}

同样,可以将结果反序列化:

Writer writer1 = gson.fromJson(json, Writer.class);

这里有一些注意事项,我需要提醒你。

1)推荐使用 private 修饰字段。

2)不需要使用任何的注解来表明哪些字段需要序列化,哪些字段不需要序列化。默认情况下,包括所有的字段,以及从父类继承过来的字段。

3)如果一个字段被 transient 关键字修饰的话,它将不参与序列化。

4)如果一个字段的值为 null,它不会在序列化后的结果中显示。

5)JSON 中缺少的字段将在反序列化后设置为默认值,引用数据类型的默认值为 null,数字类型的默认值为 0,布尔值默认为 false。

接下来,来看一个序列化集合的例子。

List<String> list =new ArrayList<>();

list.add(“好好学习”);

list.add(“天天向上”);

String json = gson.toJson(list);

结果如下所示:

[“好好学习”,“天天向上”]

反序列化的时候,也很简单。

List<String> listResult = gson.fromJson(json,List.class);

结果如下所示:

[好好学习, 天天向上]

我女朋友是一个很细心也很贴心的人,在你调用 toJson() 方法进行序列化的时候,她会先判 null,防止抛出 NPE,再通过 getClass() 获取参数的类型,然后进行序列化。

public String toJson(Object src) {

if (src == null) {

return toJson(JsonNull.INSTANCE);

}

return toJson(src, src.getClass());

}

但是呢?对于泛型来说,getClass() 的时候会丢掉参数化类型。来看下面这个例子。

public class Foo<T> {

T value;

public void set(T value) {

this.value = value;

}

public T get() {

return value;

}

public static void main(String[] args) {

Gson gson = new Gson();

Foo<Bar> foo = new Foo<Bar>();

Bar bar = new Bar();

foo.set(bar);

String json = gson.toJson(foo);

}

}

class Bar{

private int age = 10;

private String name = “图灵”;

}

假如你 debug 的时候,进入到 toJson() 方法的内部,就可以观察到。

Gson:GitHub 标星 18K 的 JSON 解析器,Google 出品的 Java JSON 解析器_后端开发

foo 的实际类型为 Foo<Bar>,但我女朋友在调用 foo.getClass() 的时候,只会得到 Foo,这就意味着她并不知道 foo 的实际类型。

序列化的时候还好,反序列化的时候就无能为力了。

Foo<Bar> foo1 = gson.fromJson(json, foo.getClass());

Bar bar1 = foo1.get();

这段代码在运行的时候就报错了。

Exception in thread “main” java.lang.ClassCastException: class com.google.gson.internal.LinkedTreeMap cannot be cast to class com.itwanger.gson.Bar (com.google.gson.internal.LinkedTreeMap and com.itwanger.gson.Bar are in unnamed module of loader ‘app’)

at com.itwanger.gson.Foo.main(Foo.java:36)

默认情况下,泛型的参数类型会被转成 LinkedTreeMap,这显然并不是我们预期的 Bar,女朋友对此表示很无奈。

作为 Google 的亲儿子,我的血液里流淌着“贵族”二字,我又怎能忍心女朋友无助时的落寞。

于是,我在女朋友的体内植入了另外两种方法,带 Type 类型参数的:

toJson(Object src, Type typeOfSrc);

<T> T fromJson(String json, Type typeOfT);

这样的话,你在进行泛型的序列化和反序列化时,就可以指定泛型的参数化类型了。

Type fooType = new TypeToken<Foo<Bar>>() {}.getType();

String json = gson.toJson(foo,fooType);

Foo<Bar> foo1 = gson.fromJson(json, fooType);

Bar bar1 = foo1.get();

debug 进入 toJson() 方法内部查看的话,就可以看到 foo 的真实类型了。

Gson:GitHub 标星 18K 的 JSON 解析器,Google 出品的 Java JSON 解析器_面试_02

fromJson() 在反序列化的时候,和此类似。

Gson:GitHub 标星 18K 的 JSON 解析器,Google 出品的 Java JSON 解析器_后端开发_03

这样的话,bar1 就可以通过 foo1.get() 到了。

瞧,我考虑得多周全,女朋友都忍不住夸我了!

 05、处理混合类型

你知道的,Java 不建议使用混合类型,也就是下面这种情况。

List list = new ArrayList();

list.add(“沉默王二”);

list.add(18);

list.add(new Event(“gson”, “google”));

Event 的定义如下所示:

class Event {

private String name;

private String source;

Event(String name, String source) {

this.name = name;

this.source = source;

}

}

由于 list 没有指定具体的类型,因此它里面可以存放各种类型的数据。这样虽然省事,我女朋友在序列化的时候也没问题,但反序列化的时候就要麻烦多了。

Gson gson = new Gson();

String json = gson.toJson(list);

System.out.println(json);

输出结果如下所示:

[“沉默王二”,18,{“name”:“gson”,“source”:“google”}]

反序列化的时候,就需要花点心思才能拿到 Event 对象。

JsonParser parser = new JsonParser();

JsonArray array = parser.parse(json).getAsJsonArray();

String message = gson.fromJson(array.get(0), String.class);

int number = gson.fromJson(array.get(1), int.class);

Event event = gson.fromJson(array.get(2), Event.class);

承认了,JsonParser 是我的前任。希望你不要喷我渣男,真不是我花心,是因为我们性格上有些不太适合。但我们仍然保持着朋友的关系,因为我们谁都没有错,只是代码更加规范了,已经很少有开发者使用混合类型了。

 06、个性化定制

考虑到你是一个追求时髦的人,我一直对自己要求很高,力争能够满足你的所有需求。这种高标准的要求,让我女朋友对我是又爱又恨。

爱的是,我这种追求完美的态度;恨的是,她有时候力不从心,帮不上忙。

使用 toJson() 序列化 Java 对象时,返回的 JSON 字符串中没有空格,很紧凑。如果你想要打印更漂亮的 JSON 格式,你需要打电话给一个叫 GsonBuilder 的老板,让他进行一些定制,然后再把复刻版邮寄给你,就像我在使用指南中提到的那样。

public class Writer {

private int age = 18;

private String name = “沉默王二”;

public static void main(String[] args) {

Writer writer = new Writer();

Gson gson = new Gson();

String json = gson.toJson(writer);

System.out.println(json);

Gson gson1 = new GsonBuilder().setPrettyPrinting().create();

String jsonOutput = gson1.toJson(writer);

System.out.println(jsonOutput);

}

}

来对比一下输出结果:

{“age”:18,“name”:“沉默王二”}

{

“age”: 18,

“name”: “沉默王二”

}

最后

终极手撕架构师的学习笔记:分布式+微服务+开源框架+性能优化

Gson:GitHub 标星 18K 的 JSON 解析器,Google 出品的 Java JSON 解析器_面试_04

本文已被 CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

版权声明
本文为[HarmonyOS学习]所创,转载请带上原文链接,感谢
https://blog.51cto.com/u_15438507/4690460

  1. Java经典面试题详解,突围金九银十面试季(附详细答案,mysql集群架构部署方案
  2. java整理,java高级特性编程及实战第一章
  3. java教程——反射,mongodb下载教程
  4. Java岗大厂面试百日冲刺 - 日积月累,每日三题【Day12,zookeeper原理作用
  5. Java后端互联网500道中高级面试题(含答案),linux钩子技术
  6. java8 Stream API及常用方法,java初级程序员面试
  7. java-集合-Map(双列)——迪迦重制版,2021Java开发社招面试解答之性能优化
  8. Flink处理函数实战之二:ProcessFunction类,java线程面试题目
  9. flex 布局详解,【Java面试题
  10. Linux basic command learning
  11. Why did docker lose to kubernetes? Docker employee readme!
  12. MySQL安装
  13. Elastic Search Aggregate Learning five: Problem Analysis of Uncertainty of sequencing results, Alibaba Java Performance Tuning Practical
  14. Installing, configuring, starting and accessing rabbitmq under Linux
  15. Oracle SQL injection summary
  16. Installation MySQL
  17. L'exposition à la photo d'essai sur la route i7 du nouveau vaisseau amiral de BMW Pure Electric a également été comparée à celle de Xiaopeng p7.
  18. spring JTA 关于异常处理的时机问题
  19. Le problème du temps de traitement des exceptions dans la JTA printanière
  20. Flink Handling Function Real War II: processfunction class, Java thread interview subject
  21. Oracle SQL injection summary
  22. [Java data structure] you must master the classic example of linked list interview (with super detailed illustration and code)
  23. Do you really know MySQL order by
  24. Record a java reference passing problem
  25. spring JTA 關於异常處理的時機問題
  26. Java - Set - Map (double file) - dija Rewriting, 2021 Java Developer's Performance Optimization
  27. Android入门教程 | OkHttp + Retrofit 取消请求的方法
  28. Java 8 Stream API and common methods, Java Junior Program interview
  29. Github 疯传!史上最强!BAT 大佬,2021年最新Java大厂面试笔试题分享
  30. git(3)Git 分支,zookeeper下载教程
  31. Java Backend Internet 500 questions d'entrevue moyennes et avancées (y compris les réponses), technologie de crochet Linux
  32. Entretien d'entretien d'usine Java post sprint de 100 jours - accumulation de jours et de mois, trois questions par jour [jour 12, fonction de principe de Zookeeper
  33. Tutoriel Java - reflection, tutoriel de téléchargement mongodb
  34. How to analyze several common key and hot issues in redis from multiple dimensions
  35. GIT (3) GIT Branch, Zookeeper Download tutoriel
  36. Tutoriel de démarrage Android | okhttp + Retrofit comment annuler une demande
  37. Design pattern [3.3] - Interpretation of cglib dynamic agent source code
  38. Share the actual operation of private collection project nodejs backend + Vue + Mysql to build a management system
  39. Springboot has 44 application initiators
  40. GitHub上霸榜久居不下的《Java面试突击宝典》,java图形用户界面设计基础
  41. GitHub上访问下载破百万的神仙文档《Java面试神技》看完我呆了,java面试问项目中遇到的问题
  42. GitHub上标星75k 超牛的《Java面试突击版,java高级工程师技能
  43. GitHub上标星2,java项目开发实训教程
  44. Docker development environment Preview
  45. JavaScript高級深入淺出:掌握 this 指向
  46. JavaScript Advanced Insight and outside: Mastering this direction
  47. Vue de l'application pratique de Javascript, drop drag Event
  48. docker 安装部署 Jenkins 2.322
  49. kafka安装
  50. 近九万字图文详解RabbitMQ
  51. Engaged in Java for one and a half years, how to break through yourself
  52. 输出9*9乘法表----java
  53. 判断一个数是不是素数-------java
  54. java项目,记录页面修改值,内部打“官司”用
  55. Docker installation Deployment Jenkins 2.322
  56. Comment porter un pantalon en hiver? Les petits hommes, les jambes épaisses et la largeur de l'entrejambe peuvent être vus. 3 techniques pour éviter la foudre
  57. MySQL下载和安装教程
  58. In depth analysis of rocketmq source code - message storage module
  59. Spring transaction management
  60. mysql恢复ibd数据,为何频频报错?