ruby-serial

Optimized serialization library for Ruby objects.

require 'ruby-serial'

str = RubySerial.dump [ :hello, 'World', 42 ]
# => "1\x00\x82\xA3obj\x93\x82\xA2\x00\xBB\xA2\x00\xEE\xA2\x00\xF1\xA5hello\xA5World*\xABshared_objs\x80"

RubySerial.load str
# => [:hello, "World", 42]

  • Fast and small: use MessagePack (binary compact storage) and don't serialize twice the same object
  • Independent of Ruby version: dump and load data across different versions
  • Keep shared objects: if an object is shared by others, serialization still keeps the reference and does not duplicate objects in memory
  • Gives the ability to fine tune which attributes of your objects are to be serialized (defaults to all)
  • Keeps backward compatibility with previously serialized versions
  • Has callbacks support to fine tune the serialization process
  • Can serialize objects having reference cycles (self-contained Arrays, Hashes, objects...)

Gem Version Inline docs Build Status Code Climate Code Climate Dependency Status

Installation

Use RubyGems to install it:

gem install ruby-serial

If you use bundler, add this into your Gemfile:

gem 'ruby-serial'


Usage

Require the library before using it:

require 'ruby-serial'

Basic API is the same as Marshal:

require 'ruby-serial'

str = RubySerial.dump({:this => 'is', :my => 'Ruby object'})

RubySerial.load(str)
# => {:this=>"is", :my=>"Ruby object"}


Specify attributes to be serialized in a class

  • Use rubyserial_only to specify a list of instance variables to serialize (can be used several times).
  • Use dont_rubyserial to specify a list of instance variables to not serialize (can be used several times).
require 'ruby-serial'

class User
  @@current_seq = 0

  attr_accessor :name, :age

  def initialize
    @seq_id = @@current_seq
    @@current_seq += 1
    @internal_id = rand(100)
  end

  rubyserial_only :name, :seq_id, :internal_id
  dont_rubyserial :internal_id
end

user = User.new
user.name = 'John'
user.age = 49
user
# => #<User:0x30e5488 @seq_id=0, @internal_id=25, @name="John", @age=49>

str = RubySerial.dump user
# Only @seq_id and @name should have been serialized.
RubySerial.load str
# => #<User:0x2a74ca0 @seq_id=0, @name="John">


Use callbacks to control the serialization process

  • rubyserial_ondump is called just before being serialized (it is possible to add instance variables to be serialized in this step).
  • rubyserial_onload is called just after being deserialized.
require 'ruby-serial'

class User
  def initialize(name)
    @name = name
    @name_shouted = @name.upcase
  end

  # Called before being serialized
  def rubyserial_ondump
    @has_been_serialized = true
  end

  # Called after being deserialized
  def rubyserial_onload
    @name_shouted = @name.upcase
  end

  # Don't serialize @name_shouted as we can get it back from @name
  dont_rubyserial :name_shouted
end

user = User.new('John')
user
# => #<User:0x2cc5650 @name="John", @name_shouted="JOHN">

str = RubySerial.dump user
# @name_shouted should be set even if it was not serialized, and @has_been_serialized should be set too
RubySerial.load str
# => #<User:0x301ee88 @name="John", @name_shouted="JOHN", @has_been_serialized=true>


Objects references are kept, even in cycles!

require 'ruby-serial'

class User
  attr_accessor :friend

  def initialize(name)
    @name = name
  end
end

user_john = User.new('John')
user_emma = User.new('Emma')
user_john.friend = user_emma
user_emma.friend = user_john
user_john
# => #<User:0x2ec6a88 @name="John", @friend=#<User:0x2e1cad8 @name="Emma", @friend=#<User:0x2ec6a88 ...>>>

str = RubySerial.dump user_john
RubySerial.load str
# => #<User:0x2815578 @name="John", @friend=#<User:0x2815278 @name="Emma", @friend=#<User:0x2815578 ...>>>



Contact

Contributions, questions, jokes? Send them to Muriel!