module RemiLib::RSConf::Serializable
Overview
The RemiLib::RSConf::Serializable module automatically generates methods
for RSConf serialization when included.
Example
require "libremiliacr"
alias RSConf = RemiLib::RSConf
class Location
include RSConf::Serializable
@[RSConf::Field(key: "lat")]
property latitude : Float64
@[RSConf::Field(key: "long")]
property longitude : Float64
end
class House
include RSConf::Serializable
property address : String
property location : Location?
end
rsStr = %|
address = "Crystal Road 1234"
location = {
lat: 12.3
long: 34.5
}
|
parsed = RSConf::Parser.parse(rsStr)
house = House.fromRsconf(parsed)
house.address # => "Crystal Road 1234"
house.location # => #<Location:0x10cd93d80 @latitude=12.3, @longitude=34.5>
Usage
Including RemiLib::RSConf::Serializable will create #toRsconf and
self.fromRsconf methods on the current class, and a constructor which
takes a RemiLib::RSConf::RSValue. By default, these methods serialize into
an RSConf object containing the value of every instance variable, the keys
being the instance variable name. Most primitives and collections supported
as instance variable values (string, integer, array, hash, etc.), along with
objects which define toRsconf and a constructor taking a
oRemiLib::RSConf::RSValue. 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 RemiLib::RSConf::Field can be placed on the instance
variable. Annotating property, getter and setter macros is also allowed.
require "libremiliacr"
alias RSConf = RemiLib::RSConf
class A
include RSConf::Serializable
@[RSConf::Field(key: "my_key", emitNull: true)]
getter a : Int32?
end
RemiLib::RSConf::Field properties:
- ignore: if
trueskip this field in serialization and deserialization (by default false) - neverSerialize: If truthy, skip this field in serialization (default:
false). The value can be any Crystal expression and is evaluated at runtime. - neverDeserialize: if
trueskip this field in deserialization (by default false) - key: the value of the key in the json object (by default the name of the instance variable)
- root: assume the value is inside an RSConf object with a given key
(see
Object.fromRSConf(stringOrIO, root)) - converter: specify an alternate type for parsing and generation. The
converter must define
fromRsconf(RemiLib::RSConf::RSValue)andtoRsconf(value, RemiLib::RSConf::RSValue). Examples of converters are aTime::Formatinstance andTime::EpochConverterforTime. - presence: if
true, a@{{key}}Presentinstance variable and a#getter?with the same name will be generated when the key was present (even if it has anullvalue),falseby default - emitNull: if
true, emits anullvalue for nilable property (by default nulls are not emitted)
Deserialization also respects default values of variables:
require "libremiliacr"
alias RSConf = RemiLib::RSConf
struct A
include RSConf::Serializable
@a : Int32
@b : Float64 = 1.0
end
data = RSConf::Parser.parse(%|a = 1|)
A.fromRsconf(data) # => A(@a=1, @b=1.0)
Extensions: RemiLib::RSConf::Serializable::Strict and
RemiLib::RSConf::Serializable::Unmapped.
If the RemiLib::RSConf::Serializable::Strict module is included, unknown
properties in the RSConf document will raise a parse exception. By default
the unknown properties are silently ignored. If the
RemiLib::RSConf::Serializable::Unmapped module is included, unknown
properties in the RSConf document will be stored in a Hash(String, RemiLib::RSConf::RSValue). On serialization, any keys inside
rsconfUnmapped will be serialized and appended to the current json object.
require "libremiliacr"
alias RSConf = RemiLib::RSConf
struct A
include RSConf::Serializable
include RSConf::Serializable::Unmapped
@a : Int32
end
data = RSConf::Parser.parse($|a = 1, b = 2|)
a = A.fromRsconf(data) # => A(@rsconfUnmapped={"b" => 2}, @a=1)
a.rsconfUnmapped["b"].raw.class # => Int64
Class annotation JSON::Serializable::Options
Supported properties:
- emitNulls: if
true, emits anullvalue for all nilable properties (by default nulls are not emitted)
require "libremiliacr"
alias RSConf = RemiLib::RSConf
@[RSConf::Serializable::Options(emitNulls: true)]
class A
include RSConf::Serializable
@a : Int32?
end
after_initialize method
#after_initialize is a method that runs after an instance is deserialized
from JSON. It can be used as a hook to post-process the initialized object.
Example:
require "libremiliacr"
alias RSConf = RemiLib::RSConf
class Person
include RSConf::Serializable
getter name : String
def after_initialize
@name = @name.upcase
end
end
data = RSConf::Parser.parse("name: jane")
person = Person.fromRsconf(data)
person.name # => "JANE"