如何避免在json的字符串中使用\“?

问题描述

春季启动应用

在build.gradle中:

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

此处JMSConfiguration:

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\"}"

以下屏幕截图:

enter image description here

然后我启动另一个应用程序(消费者)。当尝试从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\",\"createdAt\":\"2020-09-13T11:32:09.976+0300\"}"

如何避免在字符串中使用\“?

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

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

解决方法

尝试使用默认的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[]的形式发送邮件会避免不必要的转义。

,

我使用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"}"
,

转换为字符串时的问题

String message = json.toString();
jmsTemplate.convertAndSend(ESHOP_QUEUE,message);

您可以定义一个对象,该对象将被发送到队列中,例如由我们自己管理

class OrderMessage {
  private String email;
  private String action;
  private String orderId;
  //...
}

jmsTemplate.convertAndSend("mailbox",new OrderMessage(email,action,orderId));

然后Consumer

@JmsListener(.... you queue)
public void receiveMessage(OrderMessage message) {
    System.out.println(message);
}