背景:
最近在做chatAI聊天机器人时,遇到了序列化的问题。需要把用户输入的数据序列化为json数据存储在Redis中实现连续上下文对话。
- 序列化:对象 ➜ JSON / 字节,方便存储、传输
- 反序列化:JSON ➜ 对象,还原状态
序列化:
话不多说,上代码:
user是用户的名称,userInput是用户输入的数据。new MessageDTO 把数据存储到类对象中。
getHistory()他是调用了另一个反序列化的方法,稍后讲。
public List<Message> appendUserMessage(String userInput) {
MessageDTO dto = new MessageDTO("user", userInput); // ① 把用户输入封装为 DTO
//这一步是在存储的时候把JAVA对象通过RedisConfig配置进行序列化
redisTemplate.opsForList().rightPush(redisKey, dto); // ② 追加到 Redis 列表右侧
return getHistory(); // ③ 取出当前全部历史,返回给调用方
}
new MessageDTO类
public class MessageDTO {
private String role; // "user" 或 "assistant"
private String content;
public MessageDTO() {}
//全参构造器(写入 Redis 时调用)
public MessageDTO(String role, String content) {
this.role = role;
this.content = content;
}
// getter 和 setter
public String getRole() { return role; }
public void setRole(String role) { this.role = role; }
public String getContent() { return content; }
public void setContent(String content) { this.content = content; }
}
重点是RedisConfig的配置,这部分是配置Redis和Jackson(序列化/反序列化库,通过pom导入)
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
// 配置Jackson 对象映射器,支持多态序列化
ObjectMapper objectMapper = new ObjectMapper();
// 启用类型信息,保证子类反序列化正确
objectMapper.activateDefaultTyping(
LaissezFaireSubTypeValidator.instance,
ObjectMapper.DefaultTyping.NON_FINAL,
JsonTypeInfo.As.PROPERTY
);
//万能型 JSON 序列化器,可以序列化任意对象,反序列化时能根据类型信息恢复原始对象。
GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer(objectMapper);
// key 采用字符串序列化,防止类型报错
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
// value 采用带类型信息的 JSON 序列化
template.setValueSerializer(serializer);
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
}
<!--jackson序列化-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
也就是通过Redis和Jackson序列化配置把对象序列化为Json格式存储到Redis中,序列化之后的数据大概是:
{
"@class": "com.universal.main.controller.chatAi.MessageDTO",
"role": "user",
"content": "你好,爱蜜莉雅~"
}
以上就是序列化过程
反序列化:
没错回到刚才第一步getHistory()的方法:
public List<Message> getHistory() {
// ① 读出整个列表,Spring Redis (配置了Jackson)自动地把 Redis 中的 JSON 数据 反序列化为 Java 对象(Object).
List<Object> list = redisTemplate.opsForList().range(redisKey, 0, -1);
if (list == null) return List.of(); // 空则返回空列表
//封装为 Spring AI 框架所需要的标准对象
return list.stream().map(o -> { // ② 逐条转换
if (!(o instanceof MessageDTO)) {
throw new IllegalStateException("缓存数据格式错误,期望 MessageDTO,但实际是:" + o.getClass());
}
MessageDTO dto = (MessageDTO) o;
return "user".equals(dto.getRole()) // ③ 依据 role 决定类型
? new UserMessage(dto.getContent())
: new AssistantMessage(dto.getContent());
}).collect(Collectors.toList()); // ④ 返回 List<Message>
}
重点是:List<Object> list = redisTemplate.opsForList().range(redisKey, 0, -1);
因为之前在RedisConfig中配置了Jackson,它会在调用range范围读取时自动地把 Redis 中的 JSON 数据 反序列化为 Java 对象(Object).
下面部分的是为了封装为 Spring AI 框架所需要的标准对象,不用在意。
好了,以上就是反序列化和序列化的实例应用,我们可以借助Jackson简单的就能实现序列化和反序列化。希望能帮助大家!
其他:
一些序列化反序列化的常用场景: Redis 缓存、接口传参、微服务通信、消息队列

被折叠的 条评论
为什么被折叠?



