Jackson
Jackson 是一个 Java 的 JSON 处理库,广泛用于对象与 JSON 之间的转换(序列化和反序列化)。Spring Boot 默认集成了 Jackson,并将其作为 spring-boot-starter-web 依赖的一部分来处理 JSON 数据。
以下是序列化和反序列化的应用场景
| 应用场景 | 序列化 | 反序列化 |
|---|---|---|
| Spring Boot API 返回 JSON 响应 | Java 对象 → JSON | 前端请求 JSON → Java 对象 |
| 数据库存储 JSON | Java 对象 → JSON 存储 | 读取 JSON → Java 对象 |
| Redis 缓存 | Java 对象 → JSON 存入 Redis | 取出 JSON → Java 对象 |
| 消息队列(MQ) | Java 对象 → JSON 发送 | 监听 JSON → Java 对象 |
Spring Web MVC序列化和反序列化
在 Spring Boot 中,定义 @Bean ObjectMapper 会 覆盖默认的 JSON 配置,影响 @RestController 返回值、@RequestBody 解析、以及 @Autowired ObjectMapper 注入。这样可以 统一全局 JSON 格式(如时间格式、属性命名)并 修改 Jackson 默认行为,确保应用中的 JSON 处理符合需求。如果不定义,Spring Boot 会使用默认 ObjectMapper,但无法定制其行为。
配置
java
package local.ateng.java.serialize.config;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.TimeZone;
/**
* Jackson 使用 ObjectMapper 序列化和反序列化配置
*
* @author 孔余
* @email 2385569970@qq.com
* @since 2025-03-05
*/
@Configuration
public class JacksonConfig {
// 日期与时间格式化
public static String DEFAULT_TIME_ZONE = "Asia/Shanghai";
public static String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
public static String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
/**
* 自定义 Jackson 时间日期的序列化和反序列化规则
*
* @param objectMapper Jackson 的 ObjectMapper 实例
*/
public static void customizeJsonDateTime(ObjectMapper objectMapper, String timeZone,String dateFormat, String dateTimeFormat) {
// 设置全局时区,确保 Date 类型数据使用此时区
objectMapper.setTimeZone(TimeZone.getTimeZone(timeZone));
// 关闭默认时间戳序列化,改为标准格式
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
// 避免与 JavaTimeModule 冲突
objectMapper.setDateFormat(new SimpleDateFormat(dateTimeFormat));
// Java 8 时间模块
JavaTimeModule javaTimeModule = new JavaTimeModule();
// LocalDateTime 序列化 & 反序列化
javaTimeModule.addSerializer(LocalDateTime.class,
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateTimeFormat)));
javaTimeModule.addDeserializer(LocalDateTime.class,
new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(dateTimeFormat)));
// LocalDate 序列化 & 反序列化
javaTimeModule.addSerializer(LocalDate.class,
new LocalDateSerializer(DateTimeFormatter.ofPattern(dateFormat)));
javaTimeModule.addDeserializer(LocalDate.class,
new LocalDateDeserializer(DateTimeFormatter.ofPattern(dateFormat)));
// 注册 JavaTimeModule
objectMapper.registerModule(javaTimeModule);
}
/**
* 自定义 Jackson 序列化规则
*
* @param objectMapper Jackson 的 ObjectMapper 实例
*/
public static void customizeJsonSerialization(ObjectMapper objectMapper) {
// 关闭 JSON 美化输出(生产环境建议关闭,提高性能)
objectMapper.disable(SerializationFeature.INDENT_OUTPUT);
// 避免 "No serializer found for class" 异常
objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
// 过滤 null 值,减少 JSON 体积
//objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
// 过滤空集合、空字符串等无效数据,进一步精简 JSON
//objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
// 不过滤 null、空集合、空字符串等无效数据值,保持数据的原始状态
objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
// 枚举类型:使用 `toString()` 方式序列化,而不是默认的 `name()`
objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
// BigDecimal 序列化时不使用科学计数法,确保数据精确
objectMapper.enable(SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN);
// 排序字段名,保证 JSON 输出的键顺序固定(有助于缓存和数据比对)
objectMapper.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS);
// 将 Long 和 BigInteger 序列化为字符串,防止 JavaScript 丢失精度
SimpleModule simpleModule = new SimpleModule();
ToStringSerializer stringSerializer = ToStringSerializer.instance;
simpleModule.addSerializer(BigDecimal.class, stringSerializer);
simpleModule.addSerializer(BigInteger.class, stringSerializer);
simpleModule.addSerializer(Long.class, stringSerializer);
simpleModule.addSerializer(Long.TYPE, stringSerializer);
objectMapper.registerModule(simpleModule);
}
/**
* 自定义 Jackson 反序列化规则
*
* @param objectMapper Jackson 的 ObjectMapper 实例
*/
public static void customizeJsonDeserialization(ObjectMapper objectMapper) {
// 允许单个值转数组(例如 1 -> [1])
objectMapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
// 忽略未知字段(避免因缺少字段报错,提升兼容性)
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
// 处理 原始类型(如 int, long, boolean 等)在反序列化时如果遇到 null 值将其替换为默认值,而不是抛出异常
objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);
// 使用 BigDecimal 反序列化浮点数,避免精度丢失
objectMapper.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
// 使用枚举的 `toString()` 方法进行反序列化,而不是默认的 `name()`
objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
// 允许特殊字符转义
objectMapper.enable(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS);
objectMapper.enable(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER);
// 错误时提供类型检查,增强反序列化稳定性
objectMapper.enable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE);
}
/**
* 自定义 Jackson JSON 解析设置
*
* @param objectMapper Jackson 的 ObjectMapper 实例
*/
public static void customizeJsonParsing(ObjectMapper objectMapper) {
// 允许 JSON 中带注释,方便开发阶段使用
objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
// 允许字段名不带引号(可处理某些特殊格式的 JSON)
objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
// 允许单引号作为 JSON 字符串的定界符(适用于某些特殊格式)
objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
// 允许控制字符的转义(例如,`\n` 或 `\t`)
objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
// 允许反斜杠转义任何字符(如:`\\`)
objectMapper.configure(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true);
// 允许无效的 UTF-8 字符(如果 JSON 编码不完全符合标准)
objectMapper.configure(JsonParser.Feature.IGNORE_UNDEFINED, true);
// 允许 JSON 中无序字段(通常是为了性能优化)
objectMapper.configure(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS, true);
}
/**
* 配置并返回一个定制化的 ObjectMapper 实例。
* 该方法配置了日期时间格式、JSON 序列化、反序列化和解析等相关设置。
* 通过调用不同的定制方法,确保 ObjectMapper 在各种场景下都能正确处理数据。
*
* @return 配置完成的 ObjectMapper 实例
*/
@Bean
public ObjectMapper objectMapper() {
// 创建 ObjectMapper 实例
ObjectMapper objectMapper = new ObjectMapper();
// 配置日期和时间的序列化与反序列化
customizeJsonDateTime(objectMapper, DEFAULT_TIME_ZONE,DEFAULT_DATE_FORMAT,DEFAULT_DATE_TIME_FORMAT);
// 配置 JSON 序列化相关设置
customizeJsonSerialization(objectMapper);
// 配置 JSON 反序列化相关设置
customizeJsonDeserialization(objectMapper);
// 配置 JSON 解析相关设置
customizeJsonParsing(objectMapper);
// 返回配置完成的 ObjectMapper 实例
return objectMapper;
}
}1
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
使用
java
package local.ateng.java.serialize.controller;
import local.ateng.java.serialize.entity.MyUser;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
@RestController
@RequestMapping("/jackson")
public class JacksonController {
// 序列化
@GetMapping("/serialize")
public MyUser serialize() {
return MyUser.builder()
.id(1L)
.name("ateng")
.age(25)
.phoneNumber("1762306666")
.email("kongyu2385569970@gmail.com")
.score(new BigDecimal("88.911"))
.ratio(0.7147)
.birthday(LocalDate.parse("2000-01-01"))
.province("重庆市")
.city("重庆市")
.createTime(LocalDateTime.now())
.build();
}
// 反序列化
@PostMapping("/deserialize")
public String deserialize(@RequestBody MyUser myUser) {
System.out.println(myUser);
return "ok";
}
}1
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
32
33
34
35
36
37
38
39
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
32
33
34
35
36
37
38
39
访问序列化接口
curl -X GET http://localhost:12014/jackson/serialize1
示例输出:
json
{"id":"1","name":"ateng","age":25,"phoneNumber":"1762306666","email":"kongyu2385569970@gmail.com","score":"88.911","ratio":0.7147,"birthday":"2000-01-01","province":"重庆市","city":"重庆市","createTime":"2025-03-06 08:28:19","createTime2":null,"createTime3":null,"num":0,"list":null}1
访问反序列化接口
curl -X POST http://192.168.100.2:12014/jackson/deserialize \
-H "Content-Type: application/json" \
-d '{
"id": 1,
"name": "ateng",
"age": 25,
"phoneNumber": "1762306666",
"email": "kongyu2385569970@gmail.com",
"score": 88.911,
"ratio": 0.7147,
"birthday": "2000-01-01",
"province": "Chongqing",
"city": "Chongqing",
"createTime": "2025-03-05 14:30:00"
}'1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
控制台打印
MyUser(id=1, name=ateng, age=25, phoneNumber=1762306666, email=kongyu2385569970@gmail.com, score=88.911, ratio=0.7147, birthday=2000-01-01, province=Chongqing, city=Chongqing, createTime=2025-03-05T14:30, createTime2=null, createTime3=null, num=0, list=null)1
Spring Data Redis序列化和反序列化
在 Spring Data Redis 中,Jackson 主要用于将 Java 对象序列化为 JSON 存入 Redis,并在读取时反序列化回 Java 对象。由于 Redis 只能存储字符串或二进制数据,因此 RedisTemplate 需要配置合适的序列化器,如 Jackson2JsonRedisSerializer,以确保对象能正确存储和恢复。
配置
java
package local.ateng.java.serialize.config;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* RedisTemplate 配置类
* <p>
* 该类负责配置 RedisTemplate,允许对象进行序列化和反序列化。
* 在这里,我们使用了 StringRedisSerializer 来序列化和反序列化 Redis 键,
* 使用 Jackson2JsonRedisSerializer 来序列化和反序列化 Redis 值,确保 Redis 能够存储 Java 对象。
* 另外,ObjectMapper 的配置确保 JSON 的格式和解析行为符合预期。
* </p>
*/
@Configuration
public class RedisTemplateConfig {
// 日期与时间格式化
public static String DEFAULT_TIME_ZONE = "Asia/Shanghai";
public static String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
public static String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss.SSSSSS";
/**
* 自定义 ObjectMapper 配置以启用默认类型标记。
* 该方法的作用是在 JSON 序列化和反序列化时包含类类型信息,
* 以便在反序列化时能够正确地识别对象的具体类型。
*
* @param objectMapper 要配置的 ObjectMapper 实例
*/
public static void customizeJsonClassType(ObjectMapper objectMapper) {
// 启用默认类型标记,使 JSON 中包含对象的类信息
objectMapper.activateDefaultTyping(
LaissezFaireSubTypeValidator.instance, // 允许所有子类型的验证器(最宽松)
ObjectMapper.DefaultTyping.NON_FINAL, // 仅对非 final 类启用类型信息
JsonTypeInfo.As.PROPERTY // 以 JSON 属性的形式存储类型信息
);
}
/**
* 配置 RedisTemplate
* <p>
* 创建 RedisTemplate,并指定如何序列化和反序列化 Redis 中的键值。
* 该配置支持使用 Jackson2JsonRedisSerializer 序列化值,并使用 StringRedisSerializer 序列化键。
* </p>
*
* @param redisConnectionFactory Redis 连接工厂
* @return 配置好的 RedisTemplate
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
// 创建 RedisTemplate 实例
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory); // 设置连接工厂
// 使用 StringRedisSerializer 来序列化和反序列化 Redis 键
// Redis 键将被序列化为字符串类型
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
template.setKeySerializer(stringRedisSerializer); // 设置键的序列化器
template.setHashKeySerializer(stringRedisSerializer); // 设置哈希键的序列化器
// 创建 ObjectMapper 实例,用于配置 Jackson 的序列化和反序列化行为
ObjectMapper objectMapper = new ObjectMapper();
JacksonConfig.customizeJsonDateTime(objectMapper, DEFAULT_TIME_ZONE, DEFAULT_DATE_FORMAT, DEFAULT_DATE_TIME_FORMAT);
JacksonConfig.customizeJsonSerialization(objectMapper);
JacksonConfig.customizeJsonDeserialization(objectMapper);
JacksonConfig.customizeJsonParsing(objectMapper);
customizeJsonClassType(objectMapper);
// 创建 Jackson2JsonRedisSerializer,用于序列化和反序列化值
// 该序列化器使用配置好的 ObjectMapper
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer =
new Jackson2JsonRedisSerializer<>(objectMapper, Object.class);
// 设置 RedisTemplate 的值的序列化器
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setHashValueSerializer(jackson2JsonRedisSerializer); // 设置哈希值的序列化器
// 返回配置好的 RedisTemplate
template.afterPropertiesSet();
return template;
}
}1
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
使用
java
package local.ateng.java.serialize.controller;
import local.ateng.java.serialize.entity.MyUser;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
@RestController
@RequestMapping("/redis")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class RedisController {
private final RedisTemplate<String, Object> redisTemplate;
// 序列化
@GetMapping("/serialize")
public String serialize() {
MyUser myUser = MyUser.builder()
.id(1L)
.name("ateng")
.age(null)
.phoneNumber("1762306666")
.email("kongyu2385569970@gmail.com")
.score(new BigDecimal("88.911"))
.ratio(0.7147)
.birthday(LocalDate.parse("2000-01-01"))
.province(null)
.city("重庆市")
.createTime(LocalDateTime.now())
.createTime2(new Date())
.list(List.of())
.build();
redisTemplate.opsForValue().set("myUser", myUser);
return "ok";
}
// 反序列化
@GetMapping("/deserialize")
public String deserialize() {
MyUser myUser = (MyUser) redisTemplate.opsForValue().get("myUser");
System.out.println(myUser);
System.out.println(myUser.getCreateTime());
return "ok";
}
}1
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
序列化到Redis
json
{
"@class": "local.ateng.java.serialize.entity.MyUser",
"id": "1",
"name": "ateng",
"age": null,
"phoneNumber": "1762306666",
"email": "kongyu2385569970@gmail.com",
"score": [
"java.math.BigDecimal",
"88.911"
],
"ratio": 0.7147,
"birthday": "2000-01-01",
"province": null,
"city": "重庆市",
"createTime": "2025-03-06 08:46:55.760579",
"createTime2": [
"java.util.Date",
"2025-03-06 08:46:55.000760"
],
"createTime3": null,
"num": 0,
"list": [
"java.util.ImmutableCollections$ListN",
[]
]
}1
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
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
反序列化输出
MyUser(id=1, name=ateng, age=null, phoneNumber=1762306666, email=kongyu2385569970@gmail.com, score=88.911, ratio=0.7147, birthday=2000-01-01, province=null, city=重庆市, createTime=2025-03-06T08:46:55.760579, createTime2=Thu Mar 06 08:46:55 CST 2025, createTime3=null, num=0, list=[])1
自定义序列化
配置自定义序列化器
java
package local.ateng.java.serialize.serializer;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
public class DefaultValueStringSerializer extends JsonSerializer {
@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
if (value == null) {
gen.writeString("/");
} else {
gen.writeString(value + "~");
}
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
使用
使用 @JsonSerialize 的 using 和 nullsUsing 指定自定义的序列化器,最终序列化后就可以实现自定义
java
@JsonSerialize(using = DefaultValueStringSerializer.class, nullsUsing = DefaultValueStringSerializer.class)
private String province;1
2
2