clojurecheshire

Encoding records as JSON objects with additional type field in Clojure


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)?


Solution

  • (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))))