Json
概述
Tio-Boot 的 JSON 模块以抽象类 Json 为核心,方便扩展第三方实现。Tio-Boot 官方提供了五种 Json 实现,分别是 TioJson、FastJson2、Jackson、Gson 和 MixedJson,这些实现均继承自抽象类 Json。
抽象类 Json 的核心方法如下:
public abstract class Json {
public abstract String toJson(Object object);
public abstract <T> T parse(String jsonString, Class<T> type);
}如上所示,Json 抽象类定义了两个核心方法:toJson(...) 将任意 Java 对象转换为 JSON 字符串,parse(...) 将 JSON 字符串反序列化为指定类型的对象。
JSON 实现
Tio-Boot 官方默认提供了五种 Json 实现,每种实现都有其独特的特性和适用场景。
1. TioJson
TioJson 是 Tio-Boot 内置的 JSON 实现,位于 tio-utils 模块中。它主要用于将 Java 对象序列化为 JSON 字符串,不支持反序列化。
特点:
- 体积小,输出速度快。
- 仅支持序列化,不支持反序列化。
使用示例:
TioJson.getJson().toJson(object);2. FastJson2
FastJson2 是基于第三方库 FastJSON2 进行的二次封装。该实现依赖于模型和 Java Bean 的 getter 方法进行转换。
特点:
- 支持丰富的 JSON 转换功能。
- 可按照 FastJSON 官方文档配置各种转换参数。
依赖配置:
<!-- https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>${fastjson.version}</version>
</dependency>3. Jackson
Jackson 实现是基于第三方库 Jackson 进行的二次封装,与 FastJson2 类似。
特点:
- 功能强大,支持复杂的 JSON 操作。
- 广泛应用于各种 Java 项目中。
依赖配置:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.0</version>
</dependency>4. Gson
Gson 实现是基于第三方库 Gson 进行的二次封装,与 FastJson2 和 Jackson 类似。
特点:
- 简洁易用,适合快速开发。
- 支持多种自定义序列化和反序列化策略。
依赖配置:
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>5. MixedJson
MixedJson 是对 TioJson 和 FastJson2 的再一次封装。在序列化时使用 TioJson,反序列化时使用 FastJson2。
特点:
- 结合了
TioJson和FastJson2的优势。 - 提供更灵活的 JSON 转换能力。
依赖配置:
<!-- https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>${fastjson.version}</version>
</dependency>配置
Tio-Boot 默认使用 MixedJson,序列化委托 TioJson,反序列化委托 FastJson2。可通过 tio.json.provider 选择 fastjson、jackson 或 gson,也可在启动时设置自定义工厂。
默认配置
未指定 provider 时使用 MixedJsonFactory。tio.json.skipNull=true 可让当前工厂的默认输出跳过 null 字段;也可以仅在某个调用点使用 JsonUtils.toSkipNullJson。
自定义配置
可以通过 JsonManager 来设置默认的 JsonFactory,以切换到其他 JSON 实现。
示例:切换到 FastJson2
import nexus.io.tio.utils.json.FastJson2Factory;
import nexus.io.tio.utils.json.JsonManager;
JsonManager.me().setDefaultJsonFactory(new FastJson2Factory());自定义实现:
假设用户扩展了 MyJson 和 MyJsonFactory,可以通过以下方式切换到自定义实现:
import nexus.io.tio.utils.json.IJsonFactory;
import nexus.io.tio.utils.json.JsonManager;
public class JsonFactoryConfig {
public void configure(IJsonFactory factory) {
JsonManager.me().setDefaultJsonFactory(factory);
}
}使用 MixedJsonFactory:
import nexus.io.tio.utils.json.JsonManager;
import nexus.io.tio.utils.json.MixedJsonFactory;
JsonManager.me().setDefaultJsonFactory(new MixedJsonFactory());日期格式配置
可以自定义 Date 类型在序列化后的格式:
import nexus.io.tio.utils.json.JsonManager;
JsonManager.me().setDefaultDatePattern("yyyy-MM-dd");配置示例
以下是一个使用 Jackson 作为默认 JSON 实现的配置示例:
import nexus.io.annotation.AConfiguration;
import nexus.io.annotation.Initialization;
import nexus.io.tio.utils.json.JacksonFactory;
import nexus.io.tio.utils.json.JsonManager;
@AConfiguration
public class JsonConfig {
@Initialization
public void config() {
JsonManager.me().setDefaultJsonFactory(new JacksonFactory());
}
}JSON 转换用法
Tio-Boot 中的 JSON 转换主要有两类用法:使用配置的 JSON 转换器和指定某个实现进行转换。
1. 使用配置的 JSON 转换器
可以通过 Json 类直接进行 JSON 转换:
Json.getJson().toJson(object);
Json.getJson().parse(jsonString, type);2. 使用 JsonUtils 工具类
Tio-Boot 提供了 JsonUtils 工具类,简化 JSON 转换操作:
import nexus.io.tio.utils.json.JsonUtils;
JsonUtils.toJson(object);
JsonUtils.parse(jsonString, type);3. 使用指定的 JSON 实现
可以临时指定使用某个 JSON 实现进行转换,而不依赖全局配置。例如,临时使用 FastJson2 进行转换:
import nexus.io.tio.utils.json.FastJson2;
FastJson2.getJson().toJson(object);
FastJson2.getJson().parse(jsonString, type);这种用法可以在需要时绕过全局配置,使用特定的 JSON 实现。
4. 单次调用保留 Long 数值类型
为前端展示 ID 时,默认的 TioJson、MixedJson 和 FastJson2 可按全局 Long 策略输出字符串,避免 JavaScript 数值精度损失。对 JSON Schema、计数或第三方协议报文,可以在本次调用中明确保留 Long 为 JSON number,同时沿用项目选择的 JSON 实现。
| 方法 | Long 输出 | null 字段 |
|---|---|---|
JsonUtils.toJson(object) | 沿用当前实现的默认策略 | 沿用当前工厂 |
JsonUtils.toSkipNullJson(object) | 沿用当前实现的默认策略 | 跳过 |
JsonUtils.toJsonWithLongAsNumber(object) | JSON number | 沿用当前工厂 |
JsonUtils.toSkipNullJsonWithLongAsNumber(object) | JSON number | 跳过 |
新方法分别委托 Json.getJson().toJson(object, false) 和 Json.getSkipNullJson().toJson(object, false)。TioJson、MixedJson、FastJson2、Jackson、GsonJson 均支持该重载;调用不会切换全局工厂,也不会修改全局 Long 策略,可与普通序列化并发使用。原本的 String 仍输出字符串,数组中的 null 仍保留。
import com.jfinal.kit.Kv;
import nexus.io.tio.utils.json.JsonUtils;
public class NumericSchemaExample {
public static void main(String[] args) {
Kv schema = Kv.create()
.set("type", "integer")
.set("maximum", 9007199254740991L)
.set("label", "9007199254740991")
.set("description", null);
String json = JsonUtils.toSkipNullJsonWithLongAsNumber(schema);
System.out.println(json);
}
}输出中的 maximum 没有引号,label 保留引号,description 被省略:
{"type":"integer","maximum":9007199254740991,"label":"9007199254740991"}字段顺序由所选实现决定。toJsonWithLongAsNumber 沿用工厂的 null 设置:如果已启用 tio.json.skipNull,该方法也会跳过 null 字段。
自定义 Json 实现可覆写 toJson(Object object, boolean longToString),false 表示数值,true 表示字符串。未实现该重载的自定义 provider 会明确抛出 UnsupportedOperationException,便于调用方适配;原有 toJson(Object) 调用保持兼容。不要在单个请求中临时修改再恢复 Json.setLongToString,避免影响其他线程。
TioJson 详解
Tio-Boot 默认使用的 JSON 转换器是 MixedJson,其中:
- 序列化(Object 转 JSON)使用
TioJson。 - 反序列化(JSON 转 Object)使用
FastJson2。
这样设计的好处是 TioJson 更轻量,序列化速度更快,而 FastJson2 提供了强大的反序列化能力。
1. 使用 TioJson
序列化示例:
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import com.jfinal.kit.Kv;
import nexus.io.tio.utils.json.TioJson;
public class WebsiteButtonServiceTest {
@Test
public void test() {
Kv kv = Kv.by("name", "01")
.set("link", null)
.set("title", "I am the fan marketing team");
List<Kv> kvList = new ArrayList<>();
kvList.add(kv);
TioJson tioJson = new TioJson();
String json = tioJson.toJson(kvList);
System.out.println(json);
}
}输出结果:
[{ "name": "01", "link": null, "title": "I am the fan marketing team" }]2. 常见参数设置
2.1 跳过空值字段 (SkipNullValueField)
默认情况下,SkipNullValueField 的值为 false。如果字段的值为 null,则会输出 "字段名":null。例如:
[{ "name": "01", "link": null, "title": "I am the fan marketing team" }]为了减少前后端的通讯量,可以将 SkipNullValueField 设置为 true,此时值为 null 的字段将被跳过:
TioJson.setSkipNullValueField(true);修改后的输出结果:
[{ "name": "01", "title": "I am the fan marketing team" }]2.2 自定义时间戳格式 (TimestampPattern)
TioJson 默认将 java.sql.Timestamp 输出为毫秒时间戳格式。例如:
package com.sejie.admin.services;
import java.sql.Timestamp;
import org.junit.Test;
import com.jfinal.kit.Kv;
import nexus.io.tio.utils.json.JsonUtils;
public class TimestampFormatTest {
@Test
public void testWithDate() {
long currentTimeSecond = System.currentTimeMillis();
Timestamp timestamp = new Timestamp(currentTimeSecond);
Kv kv = Kv.by("date", timestamp);
String json = JsonUtils.toJson(kv);
System.out.println(json);
}
}输出结果:
{ "date": 1720423322746 }可以自定义时间戳的输出格式,例如:
import nexus.io.tio.utils.json.Json;
Json.setTimestampPattern("yyyy-MM-dd HH:mm:ss");修改后的输出结果:
{ "date": "2024-07-08 16:30:35" }依赖管理
在使用不同的 JSON 实现时,需要添加相应的依赖。以下是各实现的依赖配置示例:
TioJson
无需额外依赖,TioJson 是 Tio-Boot 内置的实现。
FastJson2
<!-- https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>${fastjson.version}</version>
</dependency>Jackson
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.0</version>
</dependency>Gson
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>MixedJson
需要同时添加 TioJson 和 FastJson2 的依赖。由于 TioJson 内置,只需添加 FastJson2 依赖:
<!-- https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>${fastjson.version}</version>
</dependency>通过以上配置和使用指南,开发者可以根据项目需求灵活选择和配置 Tio-Boot 的 JSON 实现,充分发挥其在序列化和反序列化过程中的优势。
