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

Rails存储params到text列后JSON.parse报unexpected token错误

问题根因

这个问题和字段是text还是jsonb没有关系。
你存入字段的内容是Ruby哈希对象的原生字符串表示,不是标准JSON格式:存储内容里键值对用Ruby特有的哈希火箭=>分隔,而标准JSON要求键值对用冒号:分隔,格式不符合JSON规范,自然无法用JSON.parse解析。
哪怕你把字段改成jsonb类型,直接传入ActionController::Parameters对象存储,依然会出现序列化格式错误,甚至会直接触发数据库的JSON格式校验报错。

无需修改字段类型的解决方案

不需要做数据库迁移,只要在参数序列化和模型读取逻辑上做调整即可:

  • 存储时主动将参数转为标准JSON格式
    不要直接把ActionController::Parameters对象赋值给metadata字段,先过滤掉Rails自动注入的controller、action等冗余参数,转成普通哈希后再序列化为标准JSON字符串存储,修改后的控制器代码示例:
    class NotificationsController < ApplicationController
      def create
        # 按需permit你需要接收的Webhook字段,过滤冗余参数
        valid_params = params.permit(:SmsSid, :SmsStatus).to_h
        notification = Notification.new(
          metadata: valid_params.to_json
        )
        if notification.save
          head :ok
        end
      end
    end
    
  • 配置模型自动序列化,简化读写逻辑
    在Notification模型中添加serialize配置,Rails会自动完成字段的JSON序列化/反序列化:赋值时自动把哈希转成标准JSON字符串存入text字段,读取时自动把字符串转回Ruby哈希,不需要手动调用to_json或JSON.parse,读写体验和jsonb字段基本一致:
    class Notification < ApplicationRecord
      serialize :metadata, JSON
    end
    
    配置完成后可以进一步简化控制器代码,直接传转好的哈希对象给metadata字段即可,序列化逻辑会由Rails自动处理。
历史存量数据处理

之前已经存入的旧数据是Ruby哈希格式字符串,无法直接被JSON解析,需要写一次性脚本做批量转换:

注意:如果存量数据来源不可信,禁止直接使用eval做解析,避免恶意代码执行,建议使用安全的Ruby语法解析工具处理。如果确认所有数据都是自己系统生成的可信内容,可以参考如下逻辑处理:

Notification.find_each do |notification|
  # 跳过已经是标准JSON格式的新数据
  next if JSON.parse(notification.metadata) rescue false
  # 转换旧格式数据
  old_hash = eval(notification.metadata)
  notification.update!(metadata: old_hash)
end

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 20:54:59