ActiveRecord使用JSON而不是YAML序列化

我有一个使用序列化列的模型:

class Form < ActiveRecord::Base serialize :options, Hash end 

有没有办法让这个序列化使用JSON而不是YAML?

在Rails 3.1中,你可以

 class Form < ActiveRecord::Base serialize :column, JSON end 

希望有所帮助

在Rails 3.1中,您可以使用带有serialize自定义编码器。

 class ColorCoder # Called to deserialize data to ruby object. def load(data) end # Called to convert from ruby object to serialized data. def dump(obj) end end class Fruits < ActiveRecord::Base serialize :color, ColorCoder.new end 

希望这可以帮助。

参考文献:

serialize定义: https : //github.com/rails/rails/blob/master/activerecord/lib/active_record/base.rb#L556

使用rails的默认YAML编码器: https : //github.com/rails/rails/blob/master/activerecord/lib/active_record/coders/yaml_column.rb

这是load调用的地方: https : //github.com/rails/rails/blob/master/activerecord/lib/active_record/attribute_methods/read.rb#L132

更新

看到中间的高评分答案下面的一个更合适的Rails> = 3.1的答案。 这是Rails <3.1的一个很好的答案。

可能这就是你要找的东西。

 Form.find(:first).to_json 

更新

1)安装'json' gem :

 gem install json 

2)创buildJsonWrapper类

 # lib/json_wrapper.rb require 'json' class JsonWrapper def initialize(attribute) @attribute = attribute.to_s end def before_save(record) record.send("#{@attribute}=", JsonWrapper.encrypt(record.send("#{@attribute}"))) end def after_save(record) record.send("#{@attribute}=", JsonWrapper.decrypt(record.send("#{@attribute}"))) end def self.encrypt(value) value.to_json end def self.decrypt(value) JSON.parse(value) rescue value end end 

3)添加模型callback:

 #app/models/user.rb class User < ActiveRecord::Base before_save JsonWrapper.new( :name ) after_save JsonWrapper.new( :name ) def after_find self.name = JsonWrapper.decrypt self.name end end 

4)testing它!

 User.create :name => {"a"=>"b", "c"=>["d", "e"]} 

PS:

这不太干,但是我尽力了。 如果任何人都可以修复User模型中的after_find ,那就太棒了。

我的要求在这个阶段不需要大量的代码重用,所以我的蒸馏代码是上述答案的变体:

  require "json/ext" before_save :json_serialize after_save :json_deserialize def json_serialize self.options = self.options.to_json end def json_deserialize self.options = JSON.parse(options) end def after_find json_deserialize end 

干杯,相当容易到底!

我写了我自己的YAML编码器,这需要一个默认的。 这是class级:

 class JSONColumn def initialize(default={}) @default = default end # this might be the database default and we should plan for empty strings or nils def load(s) s.present? ? JSON.load(s) : @default.clone end # this should only be nil or an object that serializes to JSON (like a hash or array) def dump(o) JSON.dump(o || @default) end end 

由于loaddump是实例方法,因此需要将实例作为第二个parameter passing才能在模型定义中进行serialize 。 这是一个例子:

 class Person < ActiveRecord::Base validate :name, :pets, :presence => true serialize :pets, JSONColumn.new([]) end 

我试着创build一个新的实例,加载一个实例,并在IRB中倾倒一个实例,并且这一切都似乎正常工作。 我也写了一篇关于它的博客文章 。

serialize :attr, JSON使用composed_of方法的serialize :attr, JSON工作原理是这样的:

  composed_of :auth, :class_name => 'ActiveSupport::JSON', :mapping => %w(url to_json), :constructor => Proc.new { |url| ActiveSupport::JSON.decode(url) } 

其中url是使用json序列化的属性,auth是模型中可用的新方法,它将json格式的值保存到url属性中。 (还没有完全testing,但似乎工作)

更简单的解决scheme是使用Michael Rykov在本博客文章中描述的composed_of 。 我喜欢这个解决scheme,因为它需要使用更less的callback。

这是它的要点:

 composed_of :settings, :class_name => 'Settings', :mapping => %w(settings to_json), :constructor => Settings.method(:from_json), :converter => Settings.method(:from_json) after_validation do |u| u.settings = u.settings if u.settings.dirty? # Force to serialize end 

Aleran,你用过Rails 3的这个方法吗? 我有些同样的问题,当我碰到Michael Rykov的这篇文章的时候,我正在走向序列化,但是在他的博客上评论是不可能的,至less在那个post上。 据我的理解,他说你不需要定义设置类,但是当我尝试这一直告诉我,设置没有定义。 所以我只是想知道你是否使用过它,还应该描述什么? 谢谢。