Object serialization: Difference between revisions

From Rosetta Code
Content added Content deleted
(Perl)
(Added serialization example for PHP.)
Line 198: Line 198:
print $s2->stringify;
print $s2->stringify;
};
};

==[[PHP]]==
[[Category:PHP]]
Serialization in PHP is straightforward. The built-in function [http://www.php.net/manual/en/function.serialize.php serialize()] handles it in a single statement.
$myObj = new Object();
$serializedObj = serialize($myObj);
In order to unserialize the object, use the [http://www.php.net/manual/en/function.unserialize.php unserialize()] function. Note that the class of object must be defined in the script where unserialization takes place, or the class' methods will be lost.


==[[Ruby]]==
==[[Ruby]]==

Revision as of 20:18, 15 July 2007

Task
Object serialization
You are encouraged to solve this task according to the task description, using any language you may know.

Create a set of data types based upon inheritance. Each data type or class should have a print command that displays the contents of an instance of that class to standard output. Create instances of each class in your inheritance hierarchy and display them to standard output. Write each of the objects to a file named objects.dat in binary form using serialization or marshalling. Read the file objects.dat and print the contents of each serialized object.

Ada

This file contains the package specification containing the public definitions of the inheritance tree rooted at the type Message. Each type in the inheritance tree has its own print procedure.

with Ada.Calendar; use Ada.Calendar;

package Messages is
   type Message is tagged record
      Timestamp : Time;
   end record;
  
   procedure Print(Item : Message);
   procedure Display(Item : Message'Class);

   type Sensor_Message is new Message with record
      Sensor_Id : Integer;
      Reading : Float;
   end record;
   
   procedure Print(Item : Sensor_Message);
   
   type Control_Message is new Message with record
      Actuator_Id : Integer;
      Command     : Float;
   end record;
  
   procedure Print(Item : Control_Message);
  
end Messages;

The next portion contains the implementation of the procedures defined in the package specification.

with Ada.Text_Io; use Ada.Text_Io;
with Ada.Integer_Text_Io; use Ada.Integer_Text_Io;
with Ada.Float_Text_IO; use Ada.Float_Text_IO;

package body Messages is

   -----------
   -- Print --
   -----------

   procedure Print (Item : Message) is
      The_Year : Year_Number;
      The_Month : Month_Number;
      The_Day   : Day_Number;
      Seconds   : Day_Duration;
   begin
      Split(Date => Item.Timestamp, Year => The_Year,
         Month => The_Month, Day => The_Day, Seconds => Seconds);
         
      Put("Time Stamp:");
      Put(Item => The_Year, Width => 4);
      Put("-");
      Put(Item => The_Month, Width => 1);
      Put("-");
      Put(Item => The_Day, Width => 1);
      New_Line;
   end Print; 

   -----------
   -- Print --
   -----------

   procedure Print (Item : Sensor_Message) is
   begin
      Print(Message(Item));
      Put("Sensor Id: ");
      Put(Item => Item.Sensor_Id, Width => 1);
      New_Line;
      Put("Reading: ");
      Put(Item => Item.Reading, Fore => 1, Aft => 4, Exp => 0);
      New_Line;
   end Print;

   -----------
   -- Print --
   -----------

   procedure Print (Item : Control_Message) is
   begin
      Print(Message(Item));
      Put("Actuator Id: ");
      Put(Item => Item.Actuator_Id, Width => 1);
      New_Line;
      Put("Command: ");
      Put(Item => Item.Command, Fore => 1, Aft => 4, Exp => 0);
      New_Line;
   end Print; 

   -------------
   ---Display --
   -------------
  
   procedure Display(Item : Message'Class) is
   begin
      Print(Item);
   end Display;
   
end Messages;

The final section of code creates objects of the three message types and performs the printing, writing, and reading. The Ada attributes 'Class'Output serialize the object and write it to the specified stream. The 'Class'Input attributes call a function automatically provided by the compiler which reads from the specified stream file and returns the object read. The Display procedure takes an object in the inheritance tree rooted at Message and dispatches the correct print procedure.

with Messages; use Messages;
with Ada.Streams.Stream_Io; use Ada.Streams.Stream_Io;
with Ada.Calendar; use Ada.Calendar;
with Ada.Text_Io;

procedure Streams_Example is
   S1 : Sensor_Message;
   M1 : Message;
   C1 : Control_Message;
   Now : Time := Clock;
   The_File : Ada.Streams.Stream_Io.File_Type;
   The_Stream : Ada.Streams.Stream_IO.Stream_Access;
begin
   S1 := (Now, 1234, 0.025);
   M1.Timestamp := Now;
   C1 := (Now, 15, 0.334);
   Display(S1);
   Display(M1);
   Display(C1);
   begin
      Open(File => The_File, Mode => Out_File,
         Name => "Messages.dat");
   exception
      when others =>
         Create(File => The_File, Name => "Messages.dat");
   end;
   The_Stream := Stream(The_File);
   Sensor_Message'Class'Output(The_Stream, S1);
   Message'Class'Output(The_Stream, M1);
   Control_Message'Class'Output(The_Stream, C1);
   Close(The_File);
   Open(File => The_File, Mode => In_File,
      Name => "Messages.dat");
   The_Stream := Stream(The_File);
   Ada.Text_Io.New_Line(2);
   while not End_Of_File(The_File) loop
      Display(Message'Class'Input(The_Stream));
   end loop;
   Close(The_File);
end Streams_Example;

Output results:

Time Stamp:2007-3-9
Sensor Id: 1234
Reading: 0.0250
Time Stamp:2007-3-9
Time Stamp:2007-3-9
Actuator Id: 15
Command: 0.3340
 

Time Stamp:2007-3-9
Sensor Id: 1234
Reading: 0.0250
Time Stamp:2007-3-9
Time Stamp:2007-3-9
Actuator Id: 15
Command: 0.3340

Perl

{
    package Greeting;
    sub new {
        my $v = 'Hello world!'; 
        bless \$v, shift;
    };
    sub stringify {
        ${shift()};
    };
};
{
    package Son::of::Greeting;
    use base qw(Greeting); # inherit methods
    sub new { # overwrite method of super class
        my $v = 'Hello world from Junior!'; 
        bless \$v, shift;
    };
};
{
    use Storable qw(store retrieve);
    package main;
    my $g1 = Greeting->new;
    my $s1 = Son::of::Greeting->new;
    print $g1->stringify;
    print $s1->stringify;

    store $g1, 'objects.dat';
    my $g2 = retrieve 'objects.dat';

    store $s1, 'objects.dat';
    my $s2 = retrieve 'objects.dat';

    print $g2->stringify;
    print $s2->stringify;
};

PHP

Serialization in PHP is straightforward. The built-in function serialize() handles it in a single statement.

$myObj = new Object();
$serializedObj = serialize($myObj);

In order to unserialize the object, use the unserialize() function. Note that the class of object must be defined in the script where unserialization takes place, or the class' methods will be lost.

Ruby

 class Being
   def initialize(speciality=nil)
     @speciality=speciality
   end
   def to_s
     "(object_id = #{object_id})\n"+"(#{self.class}):".ljust(12)+to_s4Being+(@speciality ? "\n"+" "*12+@speciality : "")
   end
   def to_s4Being
     "I am a collection of cooperative molecules with a talent for self-preservation."
   end
 end
 
 class Earthling < Being
   def to_s4Being
     "I originate from a blue planet.\n"+" "*12+to_s4Earthling
   end
 end
 
 class Mamal < Earthling
   def initialize(type)
     @type=type
   end
   def to_s4Earthling
     "I am champion in taking care of my offspring and eating eveything I can find, except mamals of type #{@type}."
   end
 end
 
 class Fish < Earthling
   def initialize(iq)
     @iq=(iq>1 ? :instrustableValue : iq)
   end
   def to_s4Earthling
     "Although I think I can think, I can't resist biting in hooks."
   end
 end
 
 class Moonling < Being
   def to_s4Being
     "My name is Janneke Maan, and apparently some Earthlings will pay me a visit."
   end
 end
 
 diverseCollection=[]
 diverseCollection << (marsian=Being.new("I come from Mars and like playing hide and seek."))
 diverseCollection << (me=Mamal.new(:human))
 diverseCollection << (nemo=Fish.new(0.99))
 diverseCollection << (jannakeMaan=Moonling.new)
 
 puts "BEGIN ORIGINAL DIVERSE COLLECTION"
 diverseCollection.each do |being|
   puts "",being.to_s
 end
 puts "END ORIGINAL DIVERSE COLLECTION"
 puts "\n"+"*"*50+"\n\n"
 
 #Marshal the diverse Array of beings
 File.open('diverseCollection.bin','w') do |fo|
   fo << Marshal.dump(diverseCollection)
 end
 
 #load the Array of diverse beings
 sameDiverseCollection=Marshal.load(File.read('diverseCollection.bin'))
 
 puts "BEGIN LOADED DIVERSE COLLECTION"
 puts(
      sameDiverseCollection.collect do |being|
        being.to_s
      end.join("\n\n")
      )
 puts "END LOADED DIVERSE COLLECTION"