RabbitMQ使用Jackson2JsonMessageConverter遇字符串双重编码问题
解决RabbitMQ中Jackson2JsonMessageConverter导致的JSON双重编码问题
问题根源
当你配置Jackson2JsonMessageConverter作为消息转换器后,调用rabbitTemplate.convertAndSend()发送JSON字符串时,转换器会将该字符串视为普通Java对象,对其进行二次JSON序列化。这就导致原本的"message": "Hello World!"被转义成\"message\": \"Hello World!\",出现双重编码。
而移除转换器虽然能解决字符串的问题,但无法处理List<List<MyObject>>这类复杂对象的反序列化需求,因此需要针对性解决。
解决方案
方案1:发送JSON字符串时绕过Jackson转换器
直接使用send()方法发送原始字节数组,避免触发Jackson的序列化逻辑:
String data = """ "message": "Hello World!" """; // 直接构建Message发送,不经过convertAndSend的转换逻辑 rabbitTemplate.send(queue, MessageBuilder.withBody(data.getBytes(StandardCharsets.UTF_8)).build());
或者为发送字符串的生产者单独配置一个不使用Jackson转换器的RabbitTemplate:
@Configuration public class RabbitMQConfig { // 原有的Jackson转换器和RabbitTemplate(用于发送List<List<MyObject>>) @Bean public RabbitTemplate objectRabbitTemplate(CachingConnectionFactory connectionFactory) { RabbitTemplate template = new RabbitTemplate(connectionFactory); template.setMessageConverter(jacksonConverter()); return template; } // 新增专门发送字符串的RabbitTemplate @Bean public RabbitTemplate stringRabbitTemplate(CachingConnectionFactory connectionFactory) { return new RabbitTemplate(connectionFactory); // 默认使用SimpleMessageConverter } @Bean public Jackson2JsonMessageConverter jacksonConverter() { return new Jackson2JsonMessageConverter(); } }
发送字符串时注入stringRabbitTemplate即可。
方案2:消费者端反向解析双重编码的字符串
如果无法修改生产者代码,可在消费者端将收到的转义字符串反序列化一次,还原原始内容:
public MessageListener getListener() { return (Message message) -> { String escapedPayload = new String(message.getBody(), StandardCharsets.UTF_8); // 使用Jackson将转义后的字符串还原为原始JSON ObjectMapper objectMapper = new ObjectMapper(); String originalJson = objectMapper.readValue(escapedPayload, String.class); System.out.println(originalJson); // 输出 "message": "Hello World!" }; }
方案3:统一使用对象传输(推荐)
定义DTO类,生产者发送Java对象而非直接发送JSON字符串,这样Jackson转换器能正确处理序列化,同时兼容复杂对象的场景:
// 定义消息DTO public class MessageDTO { private String message; // 构造器、getter public MessageDTO(String message) { this.message = message; } public String getMessage() { return message; } } // 生产者发送对象 rabbitTemplate.convertAndSend(queue, new MessageDTO("Hello World!")); // 消费者处理(推荐使用@RabbitListener简化代码) @RabbitListener(queues = "#{queueName}") public void handleMessage(MessageDTO dto) { System.out.println(dto.getMessage()); // 输出 Hello World! }
如果坚持使用MessageListener,也可以手动用转换器解析:
public MessageListener getListener() { Jackson2JsonMessageConverter converter = new Jackson2JsonMessageConverter(); return (Message message) -> { MessageDTO dto = (MessageDTO) converter.fromMessage(message); System.out.println(dto.getMessage()); }; }
内容的提问来源于stack exchange,提问作者Abubakr Shoaliev
相关产品推荐
相关产品推荐

