Cheshire's custom encoders seem suitable for this problem and I wrote a little helper function:
(defn add-rec-encoder [Rec type-token]
(add-encoder Rec
(fn [rec jg] (.writeString jg
(str (encode-map (assoc rec :type type-token) jg))))))
(defrecord A [a])
(add-rec-encoder A "A")
(encode (->A "abc"))
But it produces a strange trailing ""
.
=> {"a":"abc","type":"A"} ""
What is causing this? And is there another approach worth considering (I also need to be able to decode back to a record based on this type-token)?
(encode-map ... jg)
directly writes the encoded map to the JSON generator jg
, then returns nil
.
This means that, your call to writeString
is actually:
(.writeString jg (str nil))
which, since (str nil)
is ""
, will encode and append exactly that to the JSON generator. The correct encoder logic would be:
(defn add-rec-encoder [Rec type-token]
(add-encoder Rec
(fn [rec jg]
(encode-map (assoc rec :type type-token) jg))))