In this blog, we'll be discussing Object Marshalling. We'll define it, examine the Marshall module, and then walk through an example. We'll then compare the _dump and self._load methods in more detail. The marshalling library turns Ruby object collections into byte streams, allowing them to be stored outside of the currently active script. This data can then be read and the original objects reconstructed. So let's get straight into the discussion.
What is Object Marshalling?
You may want to save an object and send it to another program or reuse it in your next program execution when writing code. Object marshalling is used in Sidekiq. When a Sidekiq work is enqueued in a Ruby on Rails application, a serialization of the job, which is nothing more than an object, is inserted into Redis. After that, the Sidekiq process can deserialize the JSON and reconstruct the original job from it.
Object marshalling is the term used in computer programming to describe serializing and deserializing an object. Let's have a look at what Ruby has built-in to handle Object Marshalling.
NOTE:
Marshal.load is capable of deserializing practically any class loaded into the Ruby process by default. If Marshal data is loaded or taken from an untrusted source over the web, this can often lead to remote code execution.
As a result, Marshal.load is not ideal for general-purpose serialization. You should never unmarshal user-supplied data or any untrustworthy data using it.
Use JSON or another serialization style that can only load simple, 'primitive' types like String, Array, Hash, and so on if you need to deserialize untrusted data. Allowing users to define arbitrary types to deserialize into should never be allowed.
Marshal Module
Since Ruby is just an object-oriented programming language, it includes a Marshall module in its standard library that allows you to serialize and save objects. It allows you to convert an object to a byte stream that may be stored and read by another Ruby process. Let’s look at it in action.
To serialize our string, we use the Marshal.dump module method. The serialized string variable holds the return value, which contains our serialized string ser_string. You can save this string to a new file, which can then be used to recreate the original object in a subsequent operation. The Marshal.load method is then used to reconstruct the original object from the byte stream.
We can observe that the object_id of this freshly reconstituted string differs from that of the text_here string, indicating that it is a distinct object with the same contents.
The self._load Method and _dump Methods
When Marshal.dump and Marshal.load are called or invoked, the marshal_dump and marshal_load procedures are called on the object supplied as an argument.
But what if I told you that the Marshal.dump and Marshal.load methods try to invoke two more methods on the object supplied as a parameter, _dump, and self.load?
_dump Method
When using the _dump method, you must handle the serialization strategy at a lower level. You must return a string that represents the data that has to serialize. The Marshal.dump method takes precedence over _dump if both are declared.
The self._load Method
Let's take a closer look at the marshal load and _load methods.
The following are the differences between the marshal load and _load methods:
When utilizing the _load method, you must handle the deserialization approach at a lower level. You are responsible for instantiating the original object.
When the self._load function takes the serialized string as a parameter. The marshal load method takes a deserialized object as an argument.
When self._load is a class method, and the marshal load method is an instance method. Now, let’s discuss Marshal Format.
Marshal Format
Ruby objects are serialized using the Marshal format. Through three user-defined extension techniques, the format can store any object.
See the Marshal module for more on using Marshal to serialize and deserialize objects.
A stream is a serialized collection of items, as defined in this article. A group of items can be loaded from a String, an IO, or an object that implements the getc method in Ruby.
Stream Format
The major and minor versions are encoded as single bytes in the first two bytes of the stream. Ruby's version is 4.8 (stored as "x04x08"), supported by Ruby 1.8.0 and newer.
Different main versions of the Marshal format are incompatible with one another and cannot be interpreted by others. Newer minor versions of the format can understand older minor versions of the format. A 4.8 implementation can load format 4.7, whereas a 4.7 implementation cannot load format 4.8.
A byte specifying the item's type is followed by one or more bytes describing the object in the stream. When the term "object" is used, it refers to any kind that defines a Ruby object.
true, false, and nil Each of these things is one byte long. The letters "T," "F," and "0" stand for true, false, and nil, respectively.
Fixnum and long The fixnum type is used to express the sizes of marshalled arrays, hashes, instance variables, and other kinds, as well as the sizes of ruby Fixnum objects. The term "long" will be used in the following sections to refer to the format defined below, which provides complete 32-bit precision.
"x00": The integer's value is zero. There are no bytes after that.
"x01": The integer's total size is two bytes. The next byte is a positive integer that ranges from 0 to 255. To save bytes, only values between 123 and 255 should be expressed in this manner.
"xff": The integer's total size is two bytes. The next byte is a negative integer that ranges from -1 to -256.
"x02": The integer's total size is three bytes. A positive little-endian integer is represented by the following two bytes.
"xfe": The integer's total size is three bytes. A negative little-endian integer is represented by the next two bytes.
"x03": The integer's total size is four bytes. The next three bytes are a positive little-endian integer.
Frequently Asked Questions
Define marshalling in Ruby?
The marshalling library turns Ruby object collections into byte streams, allowing them to be stored outside of the presently running script.
Define serialization in Ruby?
The process of writing data from an object to a stream is known as serialization. Deserialization is the process of reading a stream into an object in reverse. When you wish to save the state of an object and then retrieve it later, this is quite beneficial. A class called Marshal can be used to serialize data in Ruby.
Define marshal load?
Load marshal (bytes) Create a value from the bytes-like object. Raise EOFError, ValueError, or TypeError if no valid value is detected. The input is ignored if there are any extra bytes.
Define Active model serializer?
The Serializer gem makes it simple to format JSON. With a single request, we will be able to pick only the data we require and access our relationships. Active Model Serializers allow you to create bespoke JSON using an object-oriented approach.
What does JSON parse do in Ruby?
In the JSON string, create saves extra information. JSON.parse uses the information to generate a correct Ruby object when invoked with the option create additions.
Conclusion
In this article, we have extensively discussed Object Marshaling and Marshal Module, with Different methods to perform various operations.
After reading about the Object Marshaling and Marshal Module, are you not feeling excited to read/explore more articles on the topic of Ruby? Don't worry; Coding Ninjas has you covered. To learn see, Coding Ninjas Archives, Ruby Documentation, Various FAQs on Ruby, and Guide to Ruby.
Refer to our guided paths on Coding Ninjas Studio to learn more about DSA, Competitive Programming, JavaScript, System Design, etc. Enroll in our courses, refer to the mock test and problems; look at the interview experiences and interview bundle for placement preparations. Check out the mock test series and participate in the contests hosted on Coding Ninjas Studio! But if you have just started your learning process and looking for questions asked by tech giants like Amazon, Microsoft, Uber, etc; you must have a look