module MessagePack::Serializable
Overview
The MessagePack::Serializable
module automatically generates methods for MessagePack serialization when included.
Example
require "msgpack"
class Location
include MessagePack::Serializable
@[MessagePack::Field(key: "lat")]
property latitude : Float64
@[MessagePack::Field(key: "lng")]
property longitude : Float64
end
class House
include MessagePack::Serializable
property address : String
property location : Location?
end
house = House.from_msgpack({address: "Crystal Road 1234", location: {"lat": 12.3, "lng": 34.5}}.to_msgpack)
house.address # => "Crystal Road 1234"
house.location # => #<Location:0x10cd93d80 @latitude=12.3, @longitude=34.5>
house.to_msgpack # => Bytes[130, 167, 97, 100, 100, 114, 101, 115, ...
houses = Array(House).from_msgpack([{address: "Crystal Road 1234", location: {"lat": 12.3, "lng": 34.5}}].to_msgpack)
houses.size # => 1
houses.to_msgpack # => Bytes[145, 130, 167, 97, 100, 100, 114, 101, ...
Usage
Including MessagePack::Serializable
will create #to_msgpack
and self.from_msgpack
methods on the current object,
and a constructor which accepts a MessagePack::Unpacker
. By default, the object serializes into a msgpack
object containing values of every instance variable, with keys equal to the variable name.
Most primitives and collections supported as instance variable values (String
, Number
, Array
, Hash
etc.),
along with objects which define #to_msgpack
and a constructor accepting a MessagePack::Unpacker
.
Union types are also supported, including unions with nil
. If multiple types in a union parse correctly,
it is undefined which one will be chosen.
To change how individual instance variables are parsed and serialized, the annotation MessagePack::Field
can be applied to an instance variable. Annotating property, getter and setter macros is also allowed.
class A
include MessagePack::Serializable
@[MessagePack::Field(key: "my_key", emit_null: true)]
getter a : Int32?
end
MessagePack::Field
properties:
- ignore: skip this field on seriazation and deserialization if ignore is
true
- key: value of the key in the msgpack object (the name of the instance variable by default)
- root: assume that the value is inside a MessagePack object with a given key (see
Object.from_msgpack(string_or_io, root)
) - converter: specify an alternate type for parsing and generation. The converter must define
.from_msgpack(MessagePack::Unpacker)
and.to_msgpack(value, MessagePack::Packer)
as class methods. Example converters areTime::Format
andTime::EpochConverter
- emit_null: emit Null value for this field if it is
nil
and emit_null istrue
. Nulls are not emitted by default
Deserialization also respects default values of variables:
struct A
include MessagePack::Serializable
@a : Int32
@b : Float64 = 1.0
end
A.from_msgpack({a: 1}.to_msgpack) # => A(@a=1, @b=1.0)
Extensions: MessagePack::Serializable::Strict
, MessagePack::Serializable::Unmapped
and MessagePack::Serializable::Presence
.
If the MessagePack::Serializable::Strict
module is included, then unknown properties in a msgpack
object would raise a parse exception on deserialization. Unknown properties are silently ignored by default.
If the MessagePack::Serializable::Unmapped
module is included, then all unknown properties in a msgpack
object would be put into the @msgpack_unmapped : Hash(String, MessagePack::Any)
variable.
Upon serialization, all keys inside @msgpack_unmapped
would be serialized and appended to the current msgpack object.
struct A
include MessagePack::Serializable
include MessagePack::Serializable::Unmapped
@a : Int32
end
a = A.from_msgpack({a: 1, b: 2}.to_msgpack) # => A(@msgpack_unmapped={"b" => 2_i64}, @a=1)
Hash(String, MessagePack::Type).from_msgpack(a.to_msgpack) # => {"a" => 1_u8, "b" => 2_u8}
If the MessagePack::Serializable::Presence
module is included, then the method #key_present?
is defined,
which allows to check if a key is present in the original msgpack object.
struct A
include MessagePack::Serializable
include MessagePack::Serializable::Presence
@a : Int32?
end
A.from_msgpack({a: 1}.to_msgpack).key_present?(:a) # => true
A.from_msgpack({b: 1}.to_msgpack).key_present?(:a) # => false
Class annotation MessagePack::Serializable::Options
supported properties:
- emit_nulls: emit Null value for nilable instance variables if emit_null is
true
. Nulls are not emitted by default
@[MessagePack::Serializable::Options(emit_nulls: true)]
class A
include MessagePack::Serializable
@a : Int32?
end