当前位置: 首页 > news >正文

Json工具(二)- GSON

1. GSON简介

Gson 是 Google 提供的Java的 JSON 序列化和反序列化库。

2. GSON的基本使用

(1)构建Gson对象


@Test
public void test0() {
    /*建造者构建*/
    Gson gson1 = new GsonBuilder().create();
    /*直接构建*/
    Gson gson2 = new Gson();
}

(2)序列化处理和反序列化处理


@Test
public void test() {
    Gson gson = new GsonBuilder().create();
    TestProduct1 testProduct = new TestProduct1();
    testProduct.setProductName("白悟空");
    testProduct.setProductId("123456");
    testProduct.setProductType("game");
    testProduct.setProductPrice(new BigDecimal(1000));
    testProduct.setProductDesc("great experience");
    String json = gson.toJson(testProduct);
    System.out.println(json);

    TestProduct2 testProduct2 = gson.fromJson(json, TestProduct2.class);
    System.out.println(testProduct2);
}

3. GSON的配置构建


@Test
public void test2() {
    Gson gson = new GsonBuilder()
            .setPrettyPrinting() // 使输出的JSON格式化为易读的格式。
            .setFormattingStyle() // 自定义JSON格式化输出格式
            .setDateFormat() // 设置日期格式
            .setExclusionStrategies() // 设置序列化和反序列化的排除策略,实现ExclusionStrategy接口,重写方法筛选不需要序列化的类里面不需要的属性
            .setFieldNamingPolicy() // 设置字段命名策略
            .setFieldNamingStrategy() // 设置字段命名策略
            .setVersion() // 设置版本控制,序列化时只处理指定版本的字段
            .setStrictness()
            .setLongSerializationPolicy() // 设置长整型的序列化策略。
            .setNumberToNumberStrategy() // 已废弃,建议使用NumberTypeAdapterFactory
            .setObjectToNumberStrategy() // 已废弃,建议使用NumberTypeAdapterFactory
            .addDeserializationExclusionStrategy() // 添加反序列化排除策略
            .addSerializationExclusionStrategy() // 添加序列化排除策略
            .disableHtmlEscaping() //  禁用HTML字符转义
            .disableJdkUnsafe() // 禁用对不安全JDK类型的支持
            .disableInnerClassSerialization() // 禁用内部类的序列化
            .enableComplexMapKeySerialization() // 启用复杂类型的Map键序列化
            .excludeFieldsWithModifiers() //  排除具有指定修饰符的字段。
            .registerTypeAdapter() // 注册自定义类型适配器
            .registerTypeAdapterFactory() // 注册自定义类型适配器工厂
            .registerTypeHierarchyAdapter() // 注册自定义类型适配器
            .serializeNulls() // 序列化空值
            .create();
}

4. GSON注解说明

@Expose:指定字段是否参与序列化和反序列化


@Expose(serialize = true, deserialize = true)
private String name;

@JsonAdapter:指定自定义的类型适配器来处理特定字段的序列化和反序列化。


@JsonAdapter(CustomTypeAdapter.class)
private SomeType customField;

@SerializedName: 指定JSON字段名称与Java字段名称的映射关系


@SerializedName("json_name")
private String javaName;

@Since:指定字段的版本,只有在指定版本及以上时,字段才会被序列化和反序列化


@Since(1.0)
private String versionedField;

@Util:指定字段的版本,只有在指定版本以下时,字段才会被序列化和反序列化。


@Until(1.5)
private String deprecatedField;

5. GSON自定义序列化和反序列化

Gson自定义序列化和反序列化有两种常见的实现方式:

1. 实现JsonSerializer和JsonDeserializer接口,重写其序列化和反序列化方法。需要在创建Gson的时候注册到Gson中,或者结合@JsonAdapter注解使用。
2. 继承TypeAdapter重写read和write方法。需要在创建Gson的时候注册到Gson中,或者结合@JsonAdapter注解使用自定义的TypeAdapter。

(1)实现JsonSerializer和JsonDeserializer接口自定义序列化和反序列化
实现JsonSerializer和JsonDeserializer接口,结合@JsonAdapter注解实现序列化和反序列化,案例如下:


(2)继承TypeAdapter自定义序列化和反序列化


6. GSON的序列化与反序列化流程

7.JsonReader

(1)JsonReader介绍

JsonReader是流JSON解析器,并且是拉式解析器的示例。推送解析器解析JSON令牌并将其推送到事件处理器中。

(2)令牌

在流模式下,每个 JSON 数据都被视为一个单独的令牌。 当我们使用JsonReader处理它时,每个令牌将被顺序处理。 例如,

{"name":"xuyuan"}

在使用JsonReader进行解析时,上述 JSON 将生成 4 个令牌:

令牌 1={
令牌 2=name
令牌 3=xuyuan
令牌 4=}

(3)如何创建 GSON JsonReader

简单示例如下:

public void test() {
    String json = "{}";
    JsonReader jsonReader = new JsonReader(new StringReader(json));
}

我们可以根据 JSON 流的来源使用以下阅读器之一:

BufferedReader 
LineNumberReader
CharArrayReader
InputStreamReader
FileReader
FilterReader
PushbackReader
PipedReader
StringReader

(4)使用JsonReader处理数据

在创建包装了有效 JSON 源的JsonReader之后,我们可以开始对流令牌进行迭代并查看令牌值。 以下是在令牌上使用JsonReader读取简单
JSON 的示例。

public void test3() throws IOException {
    String json = "{'id': 1001,'firstName': 'Lokesh','lastName': 'Gupta','email': null}";
    JsonReader jsonReader = new JsonReader(new StringReader(json));
    jsonReader.setLenient(true);
    try {
        while (jsonReader.hasNext()) {
            JsonToken nextToken = jsonReader.peek();
            if (JsonToken.BEGIN_OBJECT.equals(nextToken)) {
                jsonReader.beginObject();
            } else if (JsonToken.NAME.equals(nextToken)) {
                String name = jsonReader.nextName();
                System.out.println("Token KEY >>>> " + name);
            } else if (JsonToken.STRING.equals(nextToken)) {
                String value = jsonReader.nextString();
                System.out.println("Token Value >>>> " + value);
            } else if (JsonToken.NUMBER.equals(nextToken)) {
                long value = jsonReader.nextLong();
                System.out.println("Token Value >>>> " + value);
            } else if (JsonToken.NULL.equals(nextToken)) {
                jsonReader.nextNull();
                System.out.println("Token Value >>>> null");
            } else if (JsonToken.END_OBJECT.equals(nextToken)) {
                jsonReader.endObject();
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        jsonReader.close();
    }
}

执行结果如下:

Token KEY >>>> id
Token Value >>>> 1001
Token KEY >>>> firstName
Token Value >>>> xu
Token KEY >>>> lastName
Token Value >>>> yuan
Token KEY >>>> email
Token Value >>>> null

代码说明:

JsonReader的hasNext()方法如果有更多令牌,则返回true。
peek()方法返回下一个 JSON 令牌,但不移至下一个。
随后,多次调用peek()将返回相同的 JSON 令牌。
可以使用JsonToken类的常量检查返回令牌的类型。
使用beginArray()和endArray()方法检查数组的左括号'['和']'。
使用beginObject()和endObject()方法检查对象的左括号'{'和'}'。
令牌的密钥的类型为JsonToken.NAME。 使用nextName()方法获取密钥名称。
确定令牌类型后,使用nextLong(),nextString()和nextInt()等方法获取令牌的值。
可以使用nextNull()或skipValue()使用空字面值。
所有next....()方法都返回当前令牌的值,并将内部指针移到下一个。
当遇到未知名称时,严格的解析器应该失败,并带有异常。 宽松解析器应调用skipValue()来递归地跳过该值的嵌套令牌,否则可能会发生冲突。

8.JsonWriter

(1)JsonWriter介绍

JsonWriter 是 Gson 库中的一个类,用于以流式方式写入 JSON 数据。流式写入的好处是可以有效处理大规模数据或在内存有限的情况下生成
JSON 数据。

(2)如何创建 GSON JsonReader

StringWriter stringWriter = new StringWriter(1024);
JsonWriter jsonWriter = new JsonWriter(stringWriter);

(3)使用JsonReader处理数据


@Test
public void test6() throws IOException {
    StringWriter stringWriter = new StringWriter(1024);
    JsonWriter jsonWriter = new JsonWriter(stringWriter);
    jsonWriter.beginObject();
    jsonWriter.name("name").value("xuyuan");
    jsonWriter.name("age").value(25);

    jsonWriter.name("addresses");
    jsonWriter.beginArray();
    jsonWriter.beginObject();
    jsonWriter.name("street").value("123 Main St");
    jsonWriter.name("city").value("Anytown");
    jsonWriter.endObject();
    jsonWriter.endArray();

    jsonWriter.endObject();
    jsonWriter.flush();
    jsonWriter.close();
    System.out.println(stringWriter);
}

输出结果如下:

{"name":"xuyuan","age":25,"addresses":[{"street":"123 Main St","city":"Anytown"}]}

9.JsonParser

JsonParser用于将 Json 数据解析为JsonElement并因此解析为JsonObject的解析树。 JsonObject可用于使用 JSON 字符串中的相应键来访问值。

(1)创建JsonParser

JsonParser parser = new JsonParser();

(2)解析Json

JsonParser类提供 3 种方法来提供 JSON 作为源并将其解析为JsonElement的树

* JsonElement parse(JsonReader json) – 使用JsonReader将 JSON 作为令牌流读取,并从 JSON 流中返回下一个值作为分析树。
* JsonElement parse(java.io.Reader json) – 使用指定的读取器读取 JSON,并将 JSON 字符串解析为解析树。
* JsonElement parse(java.lang.String json) - 将指定的 JSON 字符串解析为解析树。

(3)JsonElement、JsonArray、JsonNull、JsonObject、JsonPrimitive

JsonElement 是 Gson 库中所有 JSON 元素的基类。它是一个抽象类,代表了 JSON 中的任何元素。 它有多个子类,分别代表 JSON
中的不同数据结构。你可以通过 JsonElement 的实例来操作 JSON 数据,但具体的数据操作通常会涉及到其具体子类。常用方法如下:

* isJsonObject():检查该元素是否是 JsonObject。
* isJsonArray():检查该元素是否是 JsonArray。
* isJsonPrimitive():检查该元素是否是 JsonPrimitive。
* isJsonNull():检查该元素是否是 JsonNull。
* getAsJsonObject():将 JsonElement 转换为 JsonObject。
* getAsJsonArray():将 JsonElement 转换为 JsonArray。
* getAsJsonPrimitive():将 JsonElement 转换为 JsonPrimitive。
* getAsJsonNull():将 JsonElement 转换为 JsonNull。

JsonObject 表示 JSON 对象。它是 JsonElement 的一个具体实现,代表 JSON 数据中的对象结构(由键值对组成)。常用方法如下:

* add(String property, JsonElement value):向 JSON 对象中添加一个属性。
* get(String property):获取 JSON 对象中指定属性的值。
* remove(String property):从 JSON 对象中移除指定属性。
* has(String property):检查 JSON 对象中是否包含指定的属性。
* entrySet():获取 JSON 对象中所有键值对的集合。

JsonArray 表示 JSON 数组。它是 JsonElement 的一个具体实现,代表 JSON 数据中的数组结构(由一个或多个 JSON 元素组成)。常用方法如下:

* add(JsonElement element):向 JSON 数组中添加一个元素。
* get(int index):获取 JSON 数组中指定索引的元素。
* remove(int index):从 JSON 数组中移除指定索引的元素。
* size():获取 JSON 数组的元素个数。
* set(int index, JsonElement element):在指定索引处设置 JSON 数组的元素

JsonPrimitive 表示 JSON 中的原始值(基本数据类型)。它是 JsonElement 的一个具体实现,用于表示 JSON
中的字符串、数字、布尔值等原始数据类型。常用方法如下:

* getAsString():将 JsonPrimitive 转换为 String。
* getAsNumber():将 JsonPrimitive 转换为 Number。
* getAsBoolean():将 JsonPrimitive 转换为 boolean。
* isString():检查 JsonPrimitive 是否表示一个字符串。
* isNumber():检查 JsonPrimitive 是否表示一个数字。
* isBoolean():检查 JsonPrimitive 是否表示一个布尔值。

JsonNull 表示 JSON 中的 null 值。它是 JsonElement 的一个具体实现,专门用于表示 JSON 数据中的 null。常用方法如下:

* isJsonNull():检查该元素是否是 JsonNull。
* getAsJsonNull():将 JsonElement 转换为 JsonNull

(4)示例


@Test
public void test4() {
    String json = "{'id': 1001,'firstName': 'xu','lastName': 'yuan','email': null}";
    JsonElement jsonElement = new JsonParser().parse(json);
    JsonObject jsonObject = jsonElement.getAsJsonObject();

    System.out.println(jsonObject.get("id"));
    System.out.println(jsonObject.get("firstName"));
    System.out.println(jsonObject.get("lastName"));
    System.out.println(jsonObject.get("email"));
}

执行结果如下:

1001
"xu"
"yuan"
null

(5)使用fromJson()获得JsonObject


@Test
public void test5() {
    String json = "{'id': 1001,'firstName': 'xu','lastName': 'yuan','email': null}";
    JsonObject jsonObject = new Gson().fromJson(json, JsonObject.class);

    System.out.println(jsonObject.get("id"));
    System.out.println(jsonObject.get("firstName"));
    System.out.println(jsonObject.get("lastName"));
    System.out.println(jsonObject.get("email"));
}

相关文章:

  • 基于PyTorch的深度学习5—神经网络工具箱
  • STM32 Bootloader理解
  • LLM训练deepseek如何识别语音
  • linux 系统 之centos安装 docker
  • 【AI 大模型】RAG 检索增强生成 ⑧ ( 文本相似度排序 | Bi-Encoder 双编码器 | Cross-Encoder 交叉编码器 )
  • Docker 篇
  • IU5380C同步降压型2~4节多类型锂电池充电管理IC
  • 【形态学操作中的腐蚀和膨胀详解】
  • RuleOS:区块链开发的“破局者”,开启DApp创新的新纪元
  • Python入门3:类与面对对象
  • LeetCode 376. 摆动序列 java题解
  • 从 “12.3” 的崩溃到完美的解决方案:一场类型选择的冒险之旅
  • 蓝桥杯备赛-差分-重新排序
  • hive面试题--left join的坑
  • k8s集群中部署dcgm-exporter收集GPU指标
  • 机器学习 Day01人工智能概述
  • 串口数据记录仪DIY,体积小,全开源
  • 华为Mate 60 Pro+ 等机型适配支持运营商北斗卫星短信功能
  • 代码随想录算法训练营第六十一天 | 108. 冗余连接 109. 冗余连接II
  • 前端(AJAX)学习笔记(CLASS 4):进阶
  • 新华时评:让医德医风建设为健康中国护航
  • 董军同德国国防部长举行会谈
  • 证券日报:降准今日正式落地,年内或还有降准空间
  • 独行侠以1.8%概率获得状元签,NBA原来真的有剧本?
  • 中国女足将于5月17日至6月2日赴美国集训并参加邀请赛
  • 多家中小银行存款利率迈入“1时代”