You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 16:20:21