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

Spring WebSocket JSON解析失败:Unrecognized token 'object'问题排查

问题解决:Stomp消息JSON解析失败

核心问题

前端sendMessage函数中stompClient.send的参数顺序不符合Stomp规范,导致JSON消息体被错误当作headers传递,后端收到无效的"[object Object]"内容,触发JSON解析异常。

修正后的前端代码

const sendMessage = (content) => {
    if (stompClient) {
      const message = [{ content: content, sender: 'user' }];
      // 修正参数顺序:第二个参数为headers(传空对象),第三个为消息体JSON字符串
      stompClient.send(
        '/app/websocket',
        {}, // 正确的headers位置,无额外头信息时传空对象
        JSON.stringify(message)
      );
      console.log(JSON.stringify(message));
    } else {
      console.error('Stomp client is not initialized.');
    }
};

错误原因说明

Stomp客户端send方法的标准签名为:

stompClient.send(destination, headers, messageBody);
  • 第一个参数:消息目标地址
  • 第二个参数:消息头(必须是对象类型,无额外需求时传空对象{})
  • 第三个参数:消息体(JSON字符串格式)

原代码将JSON.stringify(message)放在第二个参数位置,Stomp客户端会将非对象类型的headers参数默认处理为[object Object],导致后端收到的消息体完全无效,无法被Jackson解析,最终抛出MessageConversionException。


佐证信息

前端发送的错误Frame格式

frame:
body: {}
command: "SEND"
headers:
0: "["
1: "{"
2: "\""
3: "c"
4: "o"
5: "n"
6: "t"
7: "e"
8: "n"
9: "t"
10: "\""
11: ":"
12: "\""
13: "g"
14: "o"
15: "\""
16: "," 
17: "\""
18: "s"
19: "e"
20: "n"
21: "d"
22: "e"
23: "r"
24: "\""
25: ":"
26: "\""
27: "u"
28: "s"
29: "e"
30: "r"
31: "\""
32: "}"
33: "]"
destination: "/app/websocket"

后端错误日志

org.springframework.messaging.converter.MessageConversionException: Could not read JSON: Unrecognized token 'object': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
 at [Source: (byte[])\"[object Object]\"; line: 1, column: 9]
    at org.springframework.messaging.converter.MappingJackson2MessageConverter.convertFromInternal(MappingJackson2MessageConverter.java:255) ~[spring-messaging-6.1.2.jar:6.1.2]
    at org.springframework.messaging.converter.AbstractMessageConverter.fromMessage(AbstractMessageConverter.java:183) ~[spring-messaging-6.1.2.jar:6.1.2]
    at org.springframework.messaging.converter.CompositeMessageConverter.fromMessage(CompositeMessageConverter.java:70) ~[spring-messaging-6.1.2.jar:6.1.2]
    at org.springframework.messaging.handler.annotation.support.PayloadMethodArgumentResolver.resolveArgument(PayloadMethodArgumentResolver.java:144) ~[spring-messaging-6.1.2.jar:6.1.2]
    at org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:118) ~[spring-messaging-6.1.2.jar:6.1.2]
    at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:147) ~[spring-messaging-6.1.2.jar:6.1.2]
    at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:115) ~[spring-messaging-6.1.2.jar:6.1.2]
    at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMatch(AbstractMethodMessageHandler.java:567) ~[spring-messaging-6.1.2.jar:6.1.2]
    at org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler.handleMatch(SimpAnnotationMethodMessageHandler.java:511) ~[spring-messaging-6.1.2.jar:6.1.2]
    at org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler.handleMatch(SimpAnnotationMethodMessageHandler.java:93) ~[spring-messaging-6.1.2.jar:6.1.2]
    at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessageInternal(AbstractMethodMessageHandler.java:522) ~[spring-messaging-6.1.2.jar:6.1.2]
    at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessage(AbstractMethodMessageHandler.java:457) ~[spring-messaging-6.1.2.jar:6.1.2]
    at org.springframework.messaging.support.ExecutorSubscribableChannel$SendTask.run(ExecutorSubscribableChannel.java:144) ~[spring-messaging-6.1.2.jar:6.1.2]
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[na:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[na:na]
    at java.base/java.lang.Thread.run(Thread.java:840) ~[na:na]
Caused by: com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'object': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
 at [Source: (byte[])\"[object Object]\"; line: 1, column: 9]
    at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:2477) ~[jackson-core-2.15.3.jar:2.15.3]
    at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:760) ~[jackson-core-2.15.3.jar:2.15.3]
    at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._reportInvalidToken(UTF8StreamJsonParser.java:3699) ~[jackson-core-2.15.3.jar:2.15.3]
    at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._handleUnexpectedValue(UTF8StreamJsonParser.java:2787) ~[jackson-core-2.15.3.jar:2.15.3]
    at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._nextTokenNotInObject(UTF8StreamJsonParser.java:908) ~[jackson-core-2.15.3.jar:2.15.3]
    at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextToken(UTF8StreamJsonParser.java:794) ~[jackson-core-2.15.3.jar:2.15.3]
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer._deserializeFromArray(CollectionDeserializer.java:350) ~[jackson-databind-2.15.3.jar:2.15.3]
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:244) ~[jackson-databind-2.15.3.jar:2.15.3]
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:28) ~[jackson-databind-2.15.3.jar:2.15.3]
    at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:323) ~[jackson-databind-2.15.3.jar:2.15.3]
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4825) ~[jackson-databind-2.15.3.jar:2.15.3]
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3866) ~[jackson-databind-2.15.3.jar:2.15.3]
    at org.springframework.messaging.converter.MappingJackson2MessageConverter.convertFromInternal(MappingJackson2MessageConverter.java:241) ~[spring-messaging-6.1.2.jar:6.1.2]
... 15 common frames omitted

后端Controller代码(无需修改)

@Controller
public class ChatController {
    @MessageMapping("/websocket")
    @SendTo("/topic/messages")
    public List<ChatMessage> send(@Payload List<ChatMessage> message) throws Exception {
        System.out.println("hi");
            Thread.sleep(1000); // simulated delay
        return message;
    }
}

内容的提问来源于stack exchange,提问作者kimgaeul

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 23:27:02