【问题标题】:How avoid \" in json's string?如何避免 json 字符串中的 \" ?
【发布时间】:2026-02-03 11:10:02
【问题描述】:

Spring 启动应用程序

在 build.gradle 中:

implementation 'com.google.code.gson:gson:2.7'

这里是 JMS 配置:

import org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.support.converter.MappingJackson2MessageConverter;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.jms.support.converter.MessageType;
@Configuration
@ComponentScan(basePackages = "ru.otus.software_architect.eshop")
public class JMSConfiguration {

    @Bean
    public JmsListenerContainerFactory<?> myFactory(ConnectionFactory connectionFactory,
                                                    DefaultJmsListenerContainerFactoryConfigurer configurer) {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        // This provides all boot's default to this factory, including the message converter
        configurer.configure(factory, connectionFactory);
        // You could still override some of Boot's default if necessary.
        return factory;
    }

    @Bean
    public MessageConverter jacksonJmsMessageConverter() {
        MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
        converter.setTargetType(MessageType.TEXT);
        converter.setTypeIdPropertyName("_type");
        return converter;
    }
}

这里我如何向 ActiviveMQ 发送消息:

private void sendMessageToMessageBroker(NotifyActionEnum action, int orderId) {
        JsonObject json = new JsonObject();
        json.addProperty("email", UserService.getCurrentUserName());
        json.addProperty("action", action.name().toLowerCase());
        json.addProperty("orderId", orderId);
        JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
        String message = json.toString();
        jmsTemplate.convertAndSend(ESHOP_QUEUE, message);
        logger.info("sendMessageToMessageBroker: success_sent_message_to_MB: " + message);
    }

在日志中:

success_sent_message_to_MB:

{"email":"someemail@email.com","action":"order_update","orderId":14}

不错。

但在我的队列中的 ActiveMQ 上,消息如下所示:

  "{\"email\":\"a_subscriber@mail.ru\",\"action\":\"order_update\",\"orderId\":4,\"createdAt\":\"2020-09-13T11:32:09.976+0300\"}"

这里截图:

然后我开始我的另一个应用程序(消费者)。当尝试从 json 获取日期时它被破坏了:

JsonElement messageJson = GsonUtil.parser.parse(message);
String action = messageJson.getAsJsonObject().get("action").getAsString(); // here broken

我收到错误消息:

Caused by: java.lang.IllegalStateException: Not a JSON Object: "{\"email\":\"a_subscriber@mail.ru\",\"action\":\"order_update\",\"orderId\":4,\"createdAt\":\"2020-09-13T11:32:09.976+0300\"}"

如何避免字符串中的“\”?

我需要排队成为下一个字符串:

{"email":"someemail@email.com","action":"order_update","orderId":14}

【问题讨论】:

  • 某事将字符串放在双引号中,需要转义字符串中的双引号才能正常工作。
  • @Steve 为什么在队列中显示带有 \" 的字符串?
  • 我的猜测是因为字符串开头和结尾的引号。无论添加这些引号的机制如何,都会通过在每个引号前面放置“\”来转义字符串中间的引号。为什么会这样,我不知道。
  • 您为您的JmsTemplate 配置了什么MessageConverter?您是否使用将String 转换为javax.jms.TextMessage 的默认SimpleMessageConverter
  • @JustinBertram 我更新了我的帖子

标签: spring-boot gson activemq


【解决方案1】:

尝试使用默认的MessageConverter(即SimpleMessageConverter)并将您的消息作为byte[]发送,例如:

private void sendMessageToMessageBroker(NotifyActionEnum action, int orderId) {
   JsonObject json = new JsonObject();
   json.addProperty("email", UserService.getCurrentUserName());
   json.addProperty("action", action.name().toLowerCase());
   json.addProperty("orderId", orderId);
   JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
   String message = json.toString();
   jmsTemplate.convertAndSend(ESHOP_QUEUE, message.getBytes());
   logger.info("sendMessageToMessageBroker: success_sent_message_to_MB: " + message);
}

当您以byte[] 发送消息时,SimpleMessageConverter 会将其转换为javax.jms.BytesMessage。当您的消费者收到消息时,它可以将byte[] 转换为String,如下所示:

String messageAsString;
if (message instanceof BytesMessage) {
   BytesMessage bytesMessage = (BytesMessage) message;
   byte[] buffer = new byte[(int) bytesMessage.getBodyLength()];
   bytesMessage.readBytes(buffer);   
   messageAsString = new String(buffer);
}
JsonElement messageJson = GsonUtil.parser.parse(messageAsString);
String action = messageJson.getAsJsonObject().get("action").getAsString();

我相信以byte[] 的形式发送消息将避免任何不必要的转义。

【讨论】:

  • 能否了解生产者通过 Web 控制台发送的内容?
  • 我不确定你的意思。
  • 我想通过ui工具查看{"email":"someemail@email.com","action":"order_update","orderId":14}之类的信息
  • 我不确定 ActiveMQ Web 控制台是否会将byte[] 解码为String 以供显示。请记住,消息(甚至是文本消息)可以以多种不同的方式进行编码,并且代理不一定具有将消息解码为人类可读格式所需的信息(假设存在这种格式)。
  • 我相信 Web 控制台无法从 byte[] 解码为字符串,因为 byte[] 可以是任何东西。但是 order_id 可能是一条非常有用的信息,应该可以看作是人类语言
【解决方案2】:

我使用urlEncode/decode向ActiveMQ发送消息

在我的控制器中:

private String publishToMessageBroker(NotifyActionEnum action, int orderId) {
        logger.info("publishToMessageBroker:");
        JsonObject json = new JsonObject();
        json.addProperty("email", UserService.getCurrentUserName());
        json.addProperty("action", action.name().toLowerCase());
        json.addProperty("orderId", orderId);
        json.addProperty("createdAt", DateUtil.date2String(new Date(), DateUtil.JSON_DATE_FORMAT));
        String message = json.toString();
        String urlEncodeMessage = StringUtll.urlEncode(message);
        jmsTemplate.convertAndSend(ESHOP_QUEUE, urlEncodeMessage);
        logger.info("publishToMessageBroker: success_sent_message_to_MB: " + message);
        return "Message was success published on Message Broker!"; // can use as response
}

现在在 ActiveMQ 中,消息如下所示:

"%7B%22email%22%3A%22myemail%40mail.com%22%2C%22action%22%3A%22order_delete%22%2C%22orderId%22%3A6%2C%22createdAt%22%3A%222020-09-19T12%3A20%3A57.844%2B0300%22%7D"

现在在消息接收器中我解码消息

 @JmsListener(destination = ESHOP_QUEUE)
    public void receiveMessage(String urlEncodeMessage) {
        try {
            String urlDecodeMessage = StringUtil.urlDecode(urlEncodeMessage);
            String pureDecodeMessage = StringUtil.removeFirstAndLastQuotes(urlDecodeMessage);
            JsonElement messageJson = GsonUtil.parser.parse(pureDecodeMessage);

现在工作正常。没有像 "" 这样的 mor 转义符号。

url解码后我得到纯json:

"{"email":"myemail@mail.com","action":"order_delete","orderId":6,"createdAt":"2020-09-19T12:20:57.844+0300"}"

【讨论】: