Purpose
MessagePack supports custom extension types for serializing objects that don’t have a native MessagePack representation.
References
-
Extension types reference - Detailed extension documentation
-
Custom extension types tutorial - Step-by-step guide
Concepts
Extension type format
factory.register_type(type_id, class,
packer: packer_specification,
unpacker: unpacker_specification
)Where,
-
type_idis an integer from -128 to 127 -
classis the Ruby class to serialize -
packer_specificationcan be:-
A symbol (method name to call on the object)
-
A proc (called with the object)
-
A method object
-
-
unpacker_specificationcan be:-
A symbol (class method to call)
-
A proc (called with the payload data)
-
A method object
-
Recursive extension types
factory.register_type(0x02, MyContainer,
packer: ->(obj, packer) { packer.write(obj.to_h) },
unpacker: ->(unpacker) { MyContainer.from_hash(unpacker.read) },
recursive: true
)Where,
-
recursive: trueenables nested serialization -
The
packerlambda receives the packer instance for recursive calls -
The
unpackerlambda receives the unpacker instance for recursive reads
Examples
Example 1. Custom extension type for Money objects
class Money
attr_reader :amount, :currency
def initialize(amount, currency)
@amount = amount
@currency = currency
end
def to_msgpack_ext
[amount, currency].pack("QA*")
end
def self.from_msgpack_ext(data)
amount, currency = data.unpack("QA*")
new(amount, currency)
end
end
factory = Messagepack::Factory.new
factory.register_type(0x10, Money,
packer: :to_msgpack_ext,
unpacker: :from_msgpack_ext
)
money = Money.new(1000, "USD")
binary = factory.pack(money)
result = factory.unpack(binary)
# => #<Money:0x... @amount=1000, @currency="USD">Example 2. Using procs for simple serialization
factory = Messagepack::Factory.new
# Serialize a URI object
require 'uri'
factory.register_type(0x20, URI,
packer: ->(uri) { uri.to_s },
unpacker: ->(str) { URI.parse(str) }
)
uri = URI.parse("https://example.com/path")
binary = factory.pack(uri)
result = factory.unpack(binary)
# => #<URI::HTTPS https://example.com/path>