🍛 数据转换
Forest支持JSON、XML、普通文本等数据转换形式。不需要接口调用者自己写具体的数据转换代码
# 序列化
几乎所有数据格式的转换都包含序列化和反序列化,Forest的数据转换同样如此
序列化是指,将原始的 Java 类型数据对象转化为 HTTP 请求想要发送的数据格式(如:JSON、XML、Protobuf 等)
# Content-Type 请求头
Forest中对数据进行序列化可以通过指定contentType
属性或Content-Type
头指定内容格式
@Post(
url = "http://localhost:8080/hello/user",
contentType = "application/json" // 指定contentType为application/json
)
String postJson(@Body MyUser user); // 自动将user对象序列化为JSON格式
2
3
4
5
同理,指定为application/xml
会将参数序列化为XML
格式,text/plain
则为文本,默认的application/x-www-form-urlencoded
则为表格格式。
# 请求体类型
或者,也可以通过@BodyType
注解指定type
属性
// 自动将user对象序列化为JSON格式
// 但此方式不会在请求中带有 Content-Type 请求头
@Post("http://localhost:8080/hello/user")
@BodyType("json")
String postJson(@Body MyUser user);
2
3
4
5
@BodyType
的具体使用方式,请参见《@BodyType 注解》
# Encoder
通过@BodyType
的encoder
属性设置一个具体的转换器类
// 指定仅仅使用 Jackson 转换器来序列化数据
@Post("http://localhost:8080/hello/user")
@BodyType(type = "json", encoder = ForestJacksonConverter.class)
String postJson(@Body MyUser user);
2
3
4
提示
在方法不指定 Encoder 的默认情况下,会去找接口上有没有设置 Encoder,如接口上也没有则使用全局的转换器为该方法请求的 Encoder
# 反序列化
反序列化则是正好与序列化的逆过程,是将远端服务接受到的原始数据格式(如:JSON、XML、Protobuf 等)转换为在 Java 程序中可以方便读取操作的 Java 数据对象
Forest 提供了多种反序列化的方式
# 自动识别结果数据类型
Forest 会将根据返回结果自动识别响应的数据格式,并进行反序列化转换
// 如结果是一串类似 {"a": 1, "b": 2} 形式的JSON字符串
// 则会自动识别并进行转换
@Get("http://localhost:8080/data")
Map getDataAsMap(); // 自动识别转换为 Map 对象
@Get("http://localhost:8080/data")
MyData getMyData(); // 自动识别转换为自定义类型对象
// 如结果是一串 XML 字符串
// 也能自动识别并转换
// 但前提是自定义的类型要有 JAXB 注解标注
MyXmlData getXmlData();
// 如果结果是一串类似 [{"name": "xxx"}, {"name": "yyy"}] 格式的 JSON 数组字符串
// Forest 也一样能自动识别并转换为 Java 集合对象
@Get("http://localhost:8080/data/list")
List<MyData> getDataList();
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 指定结果数据类型
您也可以通过dataType
指定返回数据的反序列化格式
@Get(
url = "http://localhost:8080/data",
dataType = "json" // 指定dataType为json,将按JSON格式反序列化数据
)
Map getData(); // 请求响应的结果将被转换为Map类型对象
2
3
4
5
# Decoder
Forest 也可以通过请求注解 (诸如:@Request
、@Get
、@Post
等) 的decoder
属性来指定具体处理该请求结果的反序列化的转换器
// 指定由 Jackson 转换器处理请求的反序列化
@Get(
url = "http://localhost:8080/data",
decoder = ForestJacksonConverter.class
)
Map getData();
2
3
4
5
6
提示
和 Encoder 一样的道理,如方法不指定 Decoder,则会去找接口上有没有设置 Decoder,如接口上也没有则使用全局的转换器为改方法请求的 Decoder
# 转换器
在Forest中,序列化和反序列化过程都有Forest转换器来实现,其数据在Forest中的转换过程如图所示:
Forest提供了默认的转换器,其分成五大类:文本转换器、JSON转换器、XML转换器、二进制转换器、自动转换器。 各大类还可以继续细分为更具体的转换器,可以按类继承理解其分类。
转换器的继承体系请看如下树状结构:
ForestConverter接口
├── DefaultTextConverter类
├── ForestJsonConverter接口
| ├── ForestFastjsonConverter类
| ├── ForestJacksonConverter类
| └── ForestGsonConverter类
├── ForestXmlConverter接口
| └── ForestJaxbConverter类
├── DefaultBinaryConverter类
└── DefaultAutoConverter类
2
3
4
5
6
7
8
9
10
可以替换和使用的转换器类如下表:
转换器类 | 类型 | 描述 |
---|---|---|
DefaultTextConverter | text | 默认文本数据转换器 |
ForestFastjsonConverter | json | 基于Fastjson框架的JSON转换器 |
ForestJacksonConverter | json | 基于Jackson框架的JSON转换器 |
ForestGsonConverter | json | 基于Gson框架的JSON转换器 |
ForestJaxbConverter | xml | 基于Jaxb框架的XML转换器 |
DefaultBinaryConverter | binary | 默认二进制转换器,多在文件下载时使用 |
DefaultAutoConverter | auto | 自动类型转换器,可以根据响应返回的数据自动嗅探数据类型并使用对应的转换器进行转换 |
# 配置全局转换器
在Forest中已定义好默认的转换器,比如JSON的默认转为器为ForestFastjsonConverter
,即FastJson
的转换器
forest:
# 转换器配置,支持 json, xml, text, binary 四种数据类型的配置
converters:
# JSON转换器
json:
# JSON转换器设置为Jackson转换器
type: com.dtflys.forest.converter.json.ForestJacksonConverter
# JSON转换器设置为GSON转换器
# type: com.dtflys.forest.converter.json.ForestGsonConverter
# JSON转换器设置为Fastjson转换器
# type: com.dtflys.forest.converter.json.ForestFastjsonConverter
# 转换器的参数设置
parameters:
# JSON数据转换器的全局日期格式化配置
dateFormat: yyyy/MM/dd HH:mm:ss
# XML转换器
xml:
# 配置为JAXB转换器
type: com.dtflys.forest.converter.xml.ForestJaxbConverter
# 二进制转换器
binary:
# 配置为Forest默认二进制转换器
type: com.dtflys.forest.converter.binary.DefaultBinaryConverter
# 文本转换器
text:
# 配置为Forest默认文本转换器
type: com.dtflys.forest.converter.text.DefaultTextConverter
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 转换器配置,支持 json, xml, text, binary 四种数据类型的配置
# JSON转换器
# JSON转换器设置为Jackson的转换器
forest.converters.json.type=com.dtflys.forest.converter.json.ForestJacksonConverter
# JSON转换器设置为GSON转换器
# forest.converters.json.type=com.dtflys.forest.converter.json.ForestGsonConverter
# JSON转换器设置为Fastjson转换器
# forest.converters.json.type=com.dtflys.forest.converter.json.ForestFastjsonConverter
# 转换器的参数设置
# JSON数据转换器的全局日期格式化配置
forest.converters.json.parameters.dateFormat: yyyy/MM/dd HH:mm:ss
# XML转换器
# 配置为JAXB转换器
forest.converters.xml.type=com.dtflys.forest.converter.xml.ForestJaxbConverter
# 二进制转换器
# 配置为Forest默认二进制转换器
forest.converters.binary.type: com.dtflys.forest.converter.binary.DefaultBinaryConverter
# 文本转换器
# 配置为Forest默认文本转换器
forest.converters.text.type: com.dtflys.forest.converter.text.DefaultTextConverter
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<forest:configuration>
<!-- Forest转换器定义 开始 -->
<!-- 设置JSON转换器 -->
<!-- JSON转换器设置为Jackson的转换器 -->
<forest:converter dataType="json" class="com.dtflys.forest.converter.json.ForestJacksonConverter">
<forest:parameter name="dateFormat" value="yyyy/MM/dd HH:mm:ss"/>
</forest:converter>
<!-- JSON转换器设置为GSON转换器 -->
<!--
<forest:converter dataType="json" class="com.dtflys.forest.converter.json.ForestGsonConverter">
<forest:parameter name="dateFormat" value="yyyy/MM/dd HH:mm:ss"/>
</forest:converter>
-->
<!-- JSON转换器设置为Fastjson转换器 -->
<!--
<forest:converter dataType="json" class="com.dtflys.forest.converter.json.ForestFastjsonConverter">
<forest:parameter name="dateFormat" value="yyyy/MM/dd HH:mm:ss"/>
</forest:converter>
-->
<!-- 设置XML转换器 -->
<forest:converter dataType="xml" class="com.dtflys.forest.converter.xml.ForestJaxbConverter">
</forest:converter>
<!-- Forest转换器定义 结束 -->
</forest:configuration>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 获取全局默认配置对象
ForestConfiguration configuration = Forest.config();
// 更换JSON转换器为FastJson
configuration.setJsonConverter(new ForestFastjsonConverter());
// 更换JSON转换器为Jackson
configuration.setJsonConverter(new ForestJacksonConverter());
// 更换JSON转换器Gson
configuration.setJsonConverter(new ForestGsonConverter());
// 更换XML转换器JAXB
configuration.getConverterMap().put(ForestDataType.XML, new ForestJaxbConverter());
2
3
4
5
6
7
8
9
10
// Make sure to add code blocks to your code group
# Springboot 下配置全局转换器
在 Springboot 环境下,可以无视上面的配置文件,取而代之的是一个更简单、更灵活、更 Springboot 的做法,即通过 @Bean
注解定义的方法返回一个ForestConverter
接口的现实类实例
# Fastjson 转换器
@Bean
public ForestJsonConverter forestFastjsonConverter() {
ForestFastjsonConverter converter = new ForestFastjsonConverter();
// 设置日期格式
converter.setDateFormat("yyyy-MM-dd HH:mm:ss");
// 设置序列化特性
converter.setSerializerFeature(SerializerFeature.IgnoreErrorGetter);
return converter;
}
2
3
4
5
6
7
8
9
# Jackson 转换器
@Bean
public ForestJsonConverter forestJacksonConverter() {
ForestJacksonConverter converter = new ForestJacksonConverter();
// 设置日期格式
converter.setDateFormat("yyyy-MM-dd HH:mm:ss");
// 获取 Jackson 的 ObjectMapper 对象
ObjectMapper mapper = converter.getMapper();
// 通过 ObjectMapper 对象可以对 Jackson 转换器做更细致的设置
return converter;
}
2
3
4
5
6
7
8
9
10
# Gson 转换器
@Bean
public ForestJsonConverter forestGsonConverter() {
ForestGsonConverter converter = new ForestGsonConverter();
// 设置日期格式
converter.setDateFormat("yyyy-MM-dd HH:mm:ss");
return converter;
}
2
3
4
5
6
7
提示
各类转换器 (如 JSON、XML转换器) 全局的 Bean 只能有一个,同时定义了多个 ForestJsonConverter (以 JSON 为例) 的 Bean 到 Spring 上下文中
则要通过上文介绍的配置方式来指定全局转换具体是哪一个
# 配置接口/方法级别转换器
使用@BodyType
注解定义encoder
// 接口级别转换器定义
@BodyType(type = "json", encoder = ForestJacksonConverter.class)
public interface MyClient {
// 方法级别转换器定义
@Get("/data")
@BodyType(type = "json", encoder = ForestFastjsonConverter.class)
String sendData(@Body MyData data);
}
2
3
4
5
6
7
8
9
具体使用方式,请参见《指定 Encoder》和《JSON 编码器快捷注解》
# 自定义转换器
请参见 《自定义转换器》