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

Rails 5 ActionCable接收外部WebSocket消息遇JSON::ParserError

解决Rails 5 ActionCable接收非JSON消息的JSON::ParserError问题

从错误堆栈可以明确,问题出在ActionCable连接的decode方法中——ActionCable默认要求所有WebSocket消息必须是JSON格式,但你无法修改外部设备的消息输出,只能在服务端做适配。之前添加的Rack中间件无效,因为WebSocket消息是连接建立后的帧数据,不属于HTTP请求周期,Rack中间件只能处理初始的握手请求,管不到后续的消息解码流程。

1. 重写ActionCable连接的decode方法

在app/channels/application_cable/connection.rb中覆盖默认的decode方法,捕获JSON解析错误,将非JSON消息转换为可处理的格式:

# app/channels/application_cable/connection.rb
module ApplicationCable
  class Connection < ActionCable::Connection::Base
    # 重写decode方法,兼容非JSON格式消息
    def decode(message)
      # 尝试用默认逻辑解析JSON
      super
    rescue JSON::ParserError => e
      # 记录原始消息,便于排查
      Rails.logger.warn "Received non-JSON message: #{message}"
      # 将纯文本消息包装为标准格式,方便频道统一处理
      { type: "plain_text", content: message }
    end
  end
end

2. 在频道中处理转换后的消息

在对应的频道类中,根据包装后的格式区分处理纯文本和JSON消息:

# 示例:app/channels/your_channel.rb
class YourChannel < ApplicationCable::Channel
  def subscribed
    stream_from "your_stream_name"
  end

  def receive(data)
    if data["type"] == "plain_text"
      # 处理纯文本消息
      handle_plain_text_message(data["content"])
    else
      # 处理原本的JSON格式消息
      handle_json_message(data)
    end
  end

  private

  def handle_plain_text_message(text)
    # 自定义处理逻辑,比如广播消息
    ActionCable.server.broadcast "your_stream_name", { message: "Received text: #{text}" }
  end

  def handle_json_message(data)
    # 原有的JSON消息处理逻辑
    # 例如:ActionCable.server.broadcast "your_stream_name", data
  end
end

3. 可选:忽略无法处理的非JSON消息

如果不需要处理纯文本消息,只想避免报错,可以在rescue块中返回空哈希或直接忽略:

def decode(message)
  super
rescue JSON::ParserError => e
  Rails.logger.debug "Ignored non-JSON message: #{message}"
  {} # 返回空哈希,频道receive方法可自行判断跳过处理
end

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 12:34:54