Gson:GitHub 标星 18K 的 JSON 解析器,Google 出品的 Java JSON 解析器,强烈推荐!(2)

简介: Gson:GitHub 标星 18K 的 JSON 解析器,Google 出品的 Java JSON 解析器,强烈推荐!

我女朋友是一个很细心也很贴心的人,在你调用 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() 方法的内部,就可以观察到。


image.png


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 的真实类型了。


image.png


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


image.png


这样的话,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"}]

1

反序列化的时候,就需要花点心思才能拿到 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": "沉默王二"

}



通过 setPrettyPrinting() 定制后,输出的格式更加层次化、立体化,字段与值之间有空格,每个不同的字段之间也会有换行。


之前提到了,默认情况下,我女朋友在序列化的时候会忽略 null 值的字段,如果不想这样的话,同样可以打电话给 GsonBuilder。


public class Writer {

   private int age = 18;

   private String name = null;


   public static void main(String[] args) {

       Writer writer = new Writer();

       Gson gson = new Gson();

       String json = gson.toJson(writer);

       System.out.println(json);


       Gson gson2 = new GsonBuilder().serializeNulls().create();

       String jsonOutput2 = gson2.toJson(writer);

       System.out.println(jsonOutput2);

   }

}



来对比一下输出结果:


{"age":18}

{"age":18,"name":null}

1

2

通过 serializeNulls() 定制后,序列化的时候就不会再忽略 null 值的字段。


也许,你在序列化和反序列化的时候想要筛选一些字段,我也考虑到这种需求了,特意为你准备了几种方案,你可以根据自己的口味挑选适合你的。


第一种,通过 Java 修饰符。


你之前也看到了,使用 transient 关键字修饰的字段将不会参与序列化和反序列化。同样的,static 关键字修饰的字段也不会。如果你想保留这些关键字修饰的字段,可以这样做。


保留单种。


Gson gson = new GsonBuilder().excludeFieldsWithModifiers(Modifier.TRANSIENT).create();


保留多种。


Gson gson = new GsonBuilder()

   .excludeFieldsWithModifiers(Modifier.STATIC, Modifier.TRANSIENT, Modifier.VOLATILE)

   .create();



第二种,通过 @Expose 注解。


要使用 @Expose 注解,你需要先这样做:


Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();


再在需要序列化和反序列化的字段上加上 @Expose 注解,如果没加的话,该字段将会被忽略。


@Expose

private int age = 18;



07、心声


如果你还想了解更多的话,请来参观我的 GitHub 主页:


https://github.com/google/gson


相关文章
|
3月前
|
JSON 缓存 自然语言处理
多语言实时数据微店商品详情API:技术实现与JSON数据解析指南
通过以上技术实现与解析指南,开发者可高效构建支持多语言的实时商品详情系统,满足全球化电商场景需求。
|
5月前
|
存储 JSON 关系型数据库
【干货满满】解密 API 数据解析:从 JSON 到数据库存储的完整流程
本文详解电商API开发中JSON数据解析与数据库存储的全流程,涵盖数据提取、清洗、转换及优化策略,结合Python实战代码与主流数据库方案,助开发者构建高效、可靠的数据处理管道。
|
4月前
|
JSON 算法 API
淘宝商品评论API接口核心解析,json数据返回
淘宝商品评论API是淘宝开放平台提供的数据服务接口,允许开发者通过编程方式获取指定商品的用户评价数据,包括文字、图片、视频评论及评分等。其核心价值在于:
|
5月前
|
人工智能 自然语言处理 并行计算
Github 12k star ,Shap‑E 深度解析:秒生成 3D 模型,一文掌握应用与技巧
Shap-E 是 OpenAI 开源的创新工具,能将文本或图片秒级转换为高质量 3D 模型,支持 Mesh 与 NeRF 格式输出。具备快速生成、双模态输入、本地部署等优势,适用于游戏原型、3D 打印、内容创作等场景,GitHub 已获 12k+ 星标。
464 0
|
2月前
|
JSON Java Go
【GoGin】(2)数据解析和绑定:结构体分析,包括JSON解析、form解析、URL解析,区分绑定的Bind方法
bind或bindXXX函数(后文中我们统一都叫bind函数)的作用就是将,以方便后续业务逻辑的处理。
289 3
|
2月前
|
XML JSON 数据处理
超越JSON:Python结构化数据处理模块全解析
本文深入解析Python中12个核心数据处理模块,涵盖csv、pandas、pickle、shelve、struct、configparser、xml、numpy、array、sqlite3和msgpack,覆盖表格处理、序列化、配置管理、科学计算等六大场景,结合真实案例与决策树,助你高效应对各类数据挑战。(238字)
229 0
|
6月前
|
JSON 定位技术 PHP
PHP技巧:解析JSON及提取数据
这就是在PHP世界里探索JSON数据的艺术。这场狩猎不仅仅是为了获得数据,而是一种透彻理解数据结构的行动,让数据在你的编码海洋中畅游。通过这次冒险,你已经掌握了打开数据宝箱的钥匙。紧握它,让你在编程世界中随心所欲地航行。
240 67
|
3月前
|
JSON 自然语言处理 API
多语言实时数据淘宝商品评论API:技术实现与JSON数据解析指南
淘宝商品评论多语言实时采集需结合官方API与后处理技术实现。建议优先通过地域站点适配获取本地化评论,辅以机器翻译完成多语言转换。在合规前提下,企业可构建多语言评论数据库,支撑全球化市场分析与产品优化。
|
8月前
|
存储 人工智能 测试技术
DeepWiki:告别迷茫!AI轻松解析Github代码库
DeepWiki 的核心目标是帮助开发者快速理解复杂的代码仓库。无论是公共仓库还是私有项目,它都可以通过简单的操作生成类似 Wikipedia 的文档页面。
|
9月前
|
数据采集 JSON 数据可视化
JSON数据解析实战:从嵌套结构到结构化表格
在信息爆炸的时代,从杂乱数据中提取精准知识图谱是数据侦探的挑战。本文以Google Scholar为例,解析嵌套JSON数据,提取文献信息并转换为结构化表格,通过Graphviz制作技术关系图谱,揭示文献间的隐秘联系。代码涵盖代理IP、请求头设置、JSON解析及可视化,提供完整实战案例。
599 4
JSON数据解析实战:从嵌套结构到结构化表格

推荐镜像

更多