# Serialization ruby 1.8 vs ruby 1.9

**URL:** <https://rubytalk.org/t/serialization-ruby-1-8-vs-ruby-1-9/56928>\
**Category:** ruby-talk\
**Created:** [7 January 2010 10:16 UTC](https://rubytalk.org/t/serialization-ruby-1-8-vs-ruby-1-9/56928 "2010-01-07T10:16:38Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Florian\_Odronitz](https://avatars.discourse-cdn.com/v4/letter/f/d9b06d/32.png) [@Florian\_Odronitz](https://rubytalk.org/u/Florian_Odronitz)\
**Post date:** [7 January 2010 10:16 UTC](https://rubytalk.org/t/serialization-ruby-1-8-vs-ruby-1-9/56928/1 "2010-01-07T10:16:38Z")

</div>

Hi,

I am trying to marshal objects with ruby 1.8 and read them with 1.9 but  
I get an error on date objects:  
ruby 1.8:  
f=File.new('/tmp/date', 'w+'); f.puts Marshal.dump(Date.today); f.close

ruby 1.9:  
m=File.read('/tmp/date'); Marshal.load(m)

gives me:  
class Date needs to have method `\_load' (TypeError)

The versions of Marshal are identical, but in 1.8, Date has a \_dump and  
\_load method, in 1.9 it does not.

Am I missing something or is this a bug?  
Any hints are appreciated.

Thanks,  
Florian

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![James\_Daniels](https://avatars.discourse-cdn.com/v4/letter/j/7993a0/32.png) [@James\_Daniels](https://rubytalk.org/u/James_Daniels)\
**Post date:** [7 January 2010 10:40 UTC](https://rubytalk.org/t/serialization-ruby-1-8-vs-ruby-1-9/56928/2 "2010-01-07T10:40:40Z")

</div>

Marshal isn't constant, it can only be expected to work when you are using the same version on Ruby.

I'd suggest using YAML.

> **···**
>
> On 2010-01-07 05:16:38 -0500, Florian Odronitz said:
> 
> > Hi,
> > 
> > I am trying to marshal objects with ruby 1.8 and read them with 1.9 but  
> > I get an error on date objects:  
> > ruby 1.8:  
> > f=File.new('/tmp/date', 'w+'); f.puts Marshal.dump(Date.today); f.close
> > 
> > ruby 1.9:  
> > m=File.read('/tmp/date'); Marshal.load(m)
> > 
> > gives me:  
> > class Date needs to have method `\_load' (TypeError)
> > 
> > The versions of Marshal are identical, but in 1.8, Date has a \_dump and  
> > \_load method, in 1.9 it does not.
> > 
> > Am I missing something or is this a bug?  
> > Any hints are appreciated.
> > 
> > Thanks,  
> > Florian

---

<div class="post-metadata">

**Author:** ![Robert\_K1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/robert_k1/32/1830_2.png) [@Robert\_K1](https://rubytalk.org/u/Robert_K1)\
**Post date:** [7 January 2010 13:10 UTC](https://rubytalk.org/t/serialization-ruby-1-8-vs-ruby-1-9/56928/3 "2010-01-07T13:10:51Z")

</div>

James is right: the format of Marshal is not guaranteed to be portable across Ruby versions. Nevertheless some types do work.

Btw, Marshal's format is binary. Which means two things

1. you should open files in binary mode,

2. printing methods like #puts are not guaranteed to work.

If you observe these rules you can make it work with Time...

robert@fussel:~$ ruby1.8 -e 'File.open("x","wb"){|i|Marshal.dump(Time.now,i)}'  
robert@fussel:~$ ls -l x  
-rw-r--r-- 1 robert robert 18 2010-01-07 13:44 x  
robert@fussel:~$ ruby19 -e 'p(File.open("x","rb"){|i|Marshal.load(i)})'  
2010-01-07 13:44:40 +0100  
robert@fussel:~$

... but apparently neither Date nor DateTime:

robert@fussel:~$ ruby1.8 -r date -e 'File.open("x","wb"){|i|Marshal.dump(Date.today,i)}'  
robert@fussel:~$ ruby19 -r date -e 'p(File.open("x","rb"){|i|Marshal.load(i)})'  
-e:1:in `load': class Date needs to have method `\_load' (TypeError)  
&nbsp;&nbsp;from -e:1:in `block in \<main\>'  
&nbsp;&nbsp;from -e:1:in `open'  
&nbsp;&nbsp;from -e:1:in `\<main\>'  
robert@fussel:~$

robert@fussel:~$ ruby1.8 -r date -e 'File.open("x","wb"){|i|Marshal.dump(DateTime.now,i)}'  
robert@fussel:~$ ruby19 -r date -e 'p(File.open("x","rb"){|i|Marshal.load(i)})'  
-e:1:in `load': class DateTime needs to have method `\_load' (TypeError)  
&nbsp;&nbsp;from -e:1:in `block in \<main\>'  
&nbsp;&nbsp;from -e:1:in `open'  
&nbsp;&nbsp;from -e:1:in `\<main\>'  
robert@fussel:~$

It does work for Date and DateTime when only using one version

robert@fussel:~$ ruby19 -r date -e 'File.open("x","wb"){|i|Marshal.dump(DateTime.now,i)}'  
robert@fussel:~$ ruby19 -r date -e 'p(File.open("x","rb"){|i|Marshal.load(i)})'  
#\<DateTime: 2010-01-07T13:54:15+01:00 (2356995876177376393/960000000000,1/24,2299161)\>  
robert@fussel:~$ ruby19 -r date -e 'File.open("x","wb"){|i|Marshal.dump(Date.today,i)}'  
robert@fussel:~$ ruby19 -r date -e 'p(File.open("x","rb"){|i|Marshal.load(i)})'  
#\<Date: 2010-01-07 (4910407/2,0,2299161)\>  
robert@fussel:~$

You have quite a few options:

1. use a type that works, e.g. String:

robert@fussel:~$ ruby1.8 -r date -e 'File.open("x","wb"){|i|Marshal.dump(Date.today.strftime,i)}'  
robert@fussel:~$ ruby19 -r date -e 'p(Date.strptime(File.open("x","rb"){|i|Marshal.load(i)}))'  
#\<Date: 2010-01-07 (4910407/2,0,2299161)\>  
robert@fussel:~$

2. create custom Marshalling and demarshalling methods which use types that work.

3. create your custom date type which encapsulates a Date but uses customized Marshal serialization.

You can see an example for customized persistence in section "Custom Persistence" on [http://blog.rubybestpractices.com/posts/rklemme/018-Complete\_Class.html](http://blog.rubybestpractices.com/posts/rklemme/018-Complete_Class.html) .

4. you use another serialization mechanism, like Yaml:

robert@fussel:~$ ruby1.8 -r date -r yaml -e 'File.open("x","wb"){|i|YAML.dump(Date.today,i)}'  
robert@fussel:~$ ruby19 -r date -r yaml -e 'p(File.open("x","rb"){|i|YAML.load(i)})'  
#\<Date: 2010-01-07 (4910407/2,0,2299161)\>  
robert@fussel:~$

5. use yet another completely different format.

There are probably more options...

Kind regards

&nbsp;&nbsp;robert

> **···**
>
> On 01/07/2010 11:16 AM, Florian Odronitz wrote:
> 
> > Hi,
> > 
> > I am trying to marshal objects with ruby 1.8 and read them with 1.9 but  
> > I get an error on date objects:  
> > ruby 1.8:  
> > f=File.new('/tmp/date', 'w+'); f.puts Marshal.dump(Date.today); f.close
> > 
> > ruby 1.9:  
> > m=File.read('/tmp/date'); Marshal.load(m)
> > 
> > gives me:  
> > class Date needs to have method `\_load' (TypeError)
> > 
> > The versions of Marshal are identical, but in 1.8, Date has a \_dump and  
> > \_load method, in 1.9 it does not.
> > 
> > Am I missing something or is this a bug?  
> > Any hints are appreciated.
> 
> --  
> remember.guy do |as, often| as.you\_can - without end  
> [http://blog.rubybestpractices.com/](http://blog.rubybestpractices.com/)

---

<div class="post-metadata">

**Author:** ![Florian\_Odronitz](https://avatars.discourse-cdn.com/v4/letter/f/d9b06d/32.png) [@Florian\_Odronitz](https://rubytalk.org/u/Florian_Odronitz)\
**Post date:** [7 January 2010 13:32 UTC](https://rubytalk.org/t/serialization-ruby-1-8-vs-ruby-1-9/56928/4 "2010-01-07T13:32:05Z")

</div>

Thank you for your very informative answers.

I was missing the thing with the binary mode. In the real use case I am  
writing to and reading from Memcache.

I tried to serialize the data with YAML and JSON which turned out to be  
far too slow.

I followed your suggestion and am now converting dates to strings and  
parsing them at the receiving end which works fine.

Cheers,  
Florian

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![Robert\_K1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/robert_k1/32/1830_2.png) [@Robert\_K1](https://rubytalk.org/u/Robert_K1)\
**Post date:** [7 January 2010 13:55 UTC](https://rubytalk.org/t/serialization-ruby-1-8-vs-ruby-1-9/56928/5 "2010-01-07T13:55:05Z")

</div>

> Thank you for your very informative answers.

You're welcome!

> I was missing the thing with the binary mode. In the real use case I am writing to and reading from Memcache.
> 
> I tried to serialize the data with YAML and JSON which turned out to be far too slow.
> 
> I followed your suggestion and am now converting dates to strings and parsing them at the receiving end which works fine.

If performance is crucial you should probably check parsing performance. I remember I did the parsing myself once because #strptime was too slow. Ah, found it:

> <https://github.com/rklemme/muppet-laboratories/blob/master/bin/sample-animal.rb>

If you can better use a numeric type like Time#to\_i or Time#to\_f. It may be that you can get at the rational inside Date.

irb(main):001:0\> d=Date.today  
=\> #\<Date: 2010-01-07 (4910407/2,0,2299161)\>  
irb(main):002:0\> d.instance\_variables  
=\> [:@sg, :@of, :@ajd, :@\_\_ca\_\_]  
irb(main):003:0\> d.instance\_variables.map {|iv| d.instance\_variable\_get(iv)}  
=\> [2299161, 0, (4910407/2), {252120=\>2455204, 258504=\>[2010, 1, 7]}]

Then you "only" need to transform that back into a Date. 🙂

Kind regards

&nbsp;&nbsp;robert

> **···**
>
> On 01/07/2010 02:32 PM, Florian Odronitz wrote:
> 
> --  
> remember.guy do |as, often| as.you\_can - without end  
> [http://blog.rubybestpractices.com/](http://blog.rubybestpractices.com/)
