CL-RemiMarshal
CL-RemiMarshal is a library for Common Lisp that allows automatic
marshalling/serializing of JSON, YAML, and
RSConf data data to and from
CLOS classes. It places emphasis on speed, and also ensuring the data is
properly typed.
CL-RemiMarshal is entirely written and maintained by one person, Remilia Scarlet! If you want to support her and CL-RemiMarshal, you can buy her a coffee on Ko-Fi, or support her through Liberapay. Support is greatly appreciated for this volunteer effort ^_^
Releases
Releases can be found on the wiki.
How do I get set up?
Most dependencies can be installed via Quicklisp. Check the .asd file to see what you'll need. The CL-SDM and CL-RemiYaml dependencies cannot, however, be installed from Quicklisp at the time of writing. This can instead be obtained from:
Once you have CL-SDM and CL-RemiYaml, put it (and this library) somewhere where ASDF can find them, then run this in a REPL:
(asdf:load-system :cl-remimarshal)
Usage
CL-RemiMarshal is based around metaclasses, which allow you to use some additional slot options to define how to marshal/unmarshal (serialize/deserialize) data using CLOS classes. It also emphasizes type checking to better ensure data integrity and code correctness.
The package nicknames cl-rm:, cl-rm/json:, cl-rm/yaml:, cl-rm/rsconf:,
and cl-rm/utils: are all defined for shorter typing.
(asdf:load-system :cl-remimarshal)
(defclass data-config ()
((store-data?
:initarg :store-data?
:initform nil
:marshal-type :bool
:accessor data-config-store-data-p))
(:metaclass cl-remimarshal-yaml:yaml-unmarshallable))
(defclass config ()
((username
:initarg :username
:initform ""
:marshal-type :string
:accessor config-username)
(hostname
:initarg :hostname
:initform nil
:key-name "host"
:marshal-type :string?
:accessor config-hostname)
(data-config
:initform (make-instance 'data-config)
:key-name "data"
:marshal-type (:class data-config)))
(:metaclass cl-remimarshal-yaml:yaml-unmarshallable))
;; Read a file into a new CONFIG instance.
(cl-remimarshal-yaml:unmarshal #P"/path/to/config.yaml" 'config)
;; Marshal a new instance to a string.
(cl-remimarshal-yaml:marshal-to-string (make-instance 'config))
The :marshal-type key can take any of the following values. The options with
? indicate "or null":
:string,:string?:bool,:bool?:list-bool,:list-bool?,:list?-bool,:list?-bool?:list-string,:list-string?,:list?-string,:list?-string?:uint8,:uint8?,:uint16,:uint16?,:uint24,:uint24?,:uint32:uint32?,:uint64,:uint64?:int8,:int8?,:int16,:int16?,:int24,:int24?,:int32:int32?,:int64,:int64?:single-float,:double-float:list-uint8,:list-uint8?,:list-uint16,:list-uint16?:list-uint24,:list-uint24?,:list-uint32,:list-uint32?:list-uint64,:list-uint64?:list-int8,:list-int8?,:list-int16,:list-int16?,:list-int24:list-int24?,:list-int32,:list-int32?,:list-int64,:list-int64?:list-single-float,:list-double-float:list?-uint8,:list?-uint8?,:list?-uint16,:list?-uint16?:list?-uint24,:list?-uint24?,:list?-uint32,:list?-uint32?:list?-uint64,:list?-uint64?:list?-int8,:list?-int8?,:list?-int16,:list?-int16?:list?-int24?,:list?-int24?,:list?-int32,:list?-int32?:list?-int64,:list?-int64?:list?-single-float,:list?-double-float:list?-single-float?,:list?-double-float?:any(store the raw deserialized value, no type checking done).
It is also possible to marhsal/unmarshal data to/from nested CLOS classes. This
is accomplished with the following values. See the files
examples/unmarshal-to-class.lisp and examples/unmarshal-to-table.lisp for
information on how to use these.
:class,:class-list,:class?,:class-list?:class-table,:class-table?
Lastly, rather than using these pre-defined types, you can also write custom
marshalling/unmarshalling functions. These use the :marshal-fn and
:unmarshal-fn slot options, respectively. A large set of predefined ones for
common usage patterns are in the :cl-remimarshal-utils package. See the files
examples/custom-functions.lisp and examples/handling-nulls.lisp for how to
use these.
Development
Style info
I use a slightly unorthodox style for my code. Aside from these differences, please use normal Lisp formatting.
- Keep lines 118 characters or shorter. Obviously sometimes you can't, but please try. Use 115 characters for Markdown files, though.
- I mark types using the form
T/..... For example,T/SOME-NEAT-TYPE. For predicates on these, useSOME-NEAT-TYPE-P. - No tabs. Only spaces.
How do I contribute?
- Go to https://chiselapp.com/user/MistressRemilia/repository/cl-remimarshal and clone the Fossil repository.
- Create a new branch for your feature.
- Push locally to the new branch.
- Create a bundle with Fossil that contains your changes.
- Get in contact with Remilia via email, Fediverse, or open a ticket.
Contributors
- Remilia Scarlet - creator and maintainer
- Homepage: https://remilia.sdf.org/
- Fediverse: @remilia@social.cyberia9.org
- Email: zremiliaz@postzeoz.jpz My real address does not contain Z's
Links and Licenses
CL-RemiMarshal is under the GNU Affero General Public License version 3.
