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

Rails中ActiveRecord错误转义JSON字符串问题求助

Rails 6.1.1中ActiveRecord Store配合jsonb字段双重转义问题解决

问题场景

在Rails 6.1.1应用中,Tweet模型的payload字段为jsonb类型,使用ActiveRecord Store直接访问字段属性:

class Tweet < ApplicationRecord
  store :payload, accessors: [:lang, :text, :entities], coder: JSON
end

添加coder: JSON是为了避免默认YAML序列化导致jsonb列存储YAML格式数据,但创建记录时出现双重转义问题:

Tweet.create payload: {foo: 'bar'}

对应的SQL日志显示payload值被处理为"\"{\\\"foo\\\":\\\"bar\\\"}\"",导致数据库中存储的是字符串嵌套字符串的形式,PostgreSQL无法使用->等JSON查询语法操作该字段,不过Rails读取记录时能正常反序列化。

解决方案

这个问题的核心是ActiveRecord Store的coder序列化与PostgreSQL对jsonb字段的原生序列化发生冲突,导致JSON被两次编码。推荐以下两种解决方法:

方法一:移除Store的coder配置(推荐)

PostgreSQL的jsonb字段本身会自动处理哈希与JSON格式的转换,不需要Store额外做JSON编码。修改模型代码:

class Tweet < ApplicationRecord
  store :payload, accessors: [:lang, :text, :entities]
end

修改后执行创建操作,SQL日志中的payload值会是标准JSON格式{"foo":"bar"},数据库存储的是原生JSON对象,既可以通过Store的accessors直接访问属性,也能正常使用PostgreSQL的JSON查询语法(如Tweet.where("payload ->> 'foo' = ?", 'bar'))。

方法二:自定义coder避免双重编码

如果因特殊需求必须保留coder配置,可以自定义序列化逻辑,确保只进行一次JSON编码:

class JsonCoder
  def self.dump(obj)
    obj.is_a?(String) ? obj : obj.to_json
  end

  def self.load(str)
    str.is_a?(Hash) ? str : JSON.parse(str) if str.present?
  end
end

class Tweet < ApplicationRecord
  store :payload, accessors: [:lang, :text, :entities], coder: JsonCoder
end

自定义的JsonCoder会判断输入类型,避免重复编码,同样能解决双重转义问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 23:30:28