trivial-json-codec
2022-07-08
A JSON parser able to identify class hierarchies.
Upstream URL
Author
License
Trivial JSON Codec Manual
[in package TRIVIAL-JSON-CODEC]
Description
A JSON parser able to handle class hierarchies.
Limitations: It expects the classes of the hierarchy to have at least one slot named differently. It does not fully follow the JSON specification.
Lists are serialized different than arrays:
(trivial-json-codec:serialize-json '(1 2 3 4)) => "<1,2,3,4>" (trivial-json-codec:serialize-json (make-array (1) :initial-contents '(1 2 3 4))) => "[1,2,3,4]"
Installing trivial-json-codec
This project is available in the latest QuickLisp distribution, so installing it is reduced to calling:
(ql:quickload :trivial-json-codec)
Working Example
The following code demonstrates the use-case for this library.
Note: The sequence '=>' indicates the result from evaluating the previous expression.
(defclass Payload () ()) (defclass SimplePayload (Payload) ((value :type integer :initarg :value))) (defclass ComplicatedPayload (Payload) ((value :type string :initarg :value) (additional-info :type string :initarg :additional-info) (message-id :type trivial-utilities:positive-fixnum :initarg :message-id))) (defclass DifferentPayload (Payload) ((cargo :type fixnum :initarg :cargo))) (defclass Message () ((uid :initarg :uid :initform nil :accessor uid) (payload :type (or null Payload) :initarg :payload :accessor payload))) (c2mop:ensure-finalized (find-class 'Payload)) (c2mop:ensure-finalized (find-class 'SimplePayload)) (c2mop:ensure-finalized (find-class 'ComplicatedPayload)) (c2mop:ensure-finalized (find-class 'DifferentPayload)) (c2mop:ensure-finalized (find-class 'Message)) (let ((message (make-instance 'Message :uid 1 :payload (make-instance 'Simplepayload :value 12345)))) (trivial-json-codec:serialize-json message)) => "{ \"UID\" : 1, \"PAYLOAD\" : { \"VALUE\" : 12345}}" (deserialize-json "{ \"UID\" : 1, \"PAYLOAD\" : { \"VALUE\" : 12345}}" :class (find-class 'Message)) => #<MESSAGE> with a payload of type SimplePayload (let ((message (make-instance 'Message :uid 2 :payload (make-instance 'ComplicatedPayload :value "abc" :message-id 17 :additional-info "1234")))) (trivial-json-codec:serialize-json message)) => "{ \"UID\" : 2, \"PAYLOAD\" : { \"VALUE\" : \"abc\", \"ADDITIONAL-INFO\" : \"1234\", \"MESSAGE-ID\" : 17}}" (deserialize-json "{ \"UID\" : 2, \"PAYLOAD\" : { \"VALUE\" : \"abc\", \"ADDITIONAL-INFO\" : \"1234\", \"MESSAGE-ID\" : 17}}" :class (find-class 'Message)) => #<MESSAGE> with a payload of type ComplicatedPayload (let ((message (make-instance 'Message :uid 2 :payload (make-instance 'DifferentPayload :cargo -147)))) (trivial-json-codec:serialize-json message)) => "{ \"UID\" : 2, \"PAYLOAD\" : { \"CARGO\" : -147}}" (deserialize-json "{ \"UID\" : 2, \"PAYLOAD\" : { \"CARGO\" : -147}}" :class (find-class 'Message)) => #<MESSAGE> with a payload of type DifferentPayload Due to the known limitation mentioned in the description, the following is NOT possible: (defclass StringPayload (Payload) ((value :type string :initarg :value))) (let ((message (make-instance 'Message :uid 2 :payload (make-instance 'StringPayload :value "abc")))) (trivial-json-codec:serialize-json message)) => "{ \"UID\" : 2, \"PAYLOAD\" : { \"VALUE" : \"abc\"}}" (deserialize-json "{ \"UID\" : 2, \"PAYLOAD\" : { \"VALUE" : \"abc\"}}" :class (find-class 'Message)) => This terminates with an error due to non-unique class mapping. StringPayload and Simplepayload differ only on the slot's type.
Exported Symbols
-
[function] SERIALIZE-JSON OBJ
Takes OBJ and serializes it into a string. Uses the generic SERIALIZE to do the job.
-
[function] DESERIALIZE-JSON JSON-STR &KEY (CLASS NIL) (READ-TABLE NIL) (CONSTRUCTORS NIL)
Reads JSON-STR and creates an according object.
If CLASS is non-nil and represents a class, an instance of it is returned. Otherwise only built-in types can be deserialized.
READ-TABLE makes it possible to inject specific readers, as pondons to SERIALIZE. It has the form of an alist containing the dispatch character as car and the deserialization function as cdr.
CONSTRUCTORS holds an alist mapping the keyword returned by a specific reader to a object construction function. -
[generic-function] SERIALIZE OBJ STREAM
Serialize an object OBJ into STREAM. Implementations for built-in types already exist. The user might extend with methods for specific types.
-
[function] DESERIALIZE-RAW JSON-STR &KEY (READ-TABLE NIL)
Deserialize JSON-STR into a property list. As opposed to DESERIALIZE-JSON this function does not require a base class to deserialize.
License Information
This library is released under the MIT License. Please refer to the LICENSE to get the full licensing text.
Contributing to this project
Please refer to the CONTRIBUTING document for more information.