一种方法可能是定义一个自定义产品语义类型,它由公共键+额外键组成。
https://github.com/cognitect/transit-format#extensibility
您将节省一些空间,但可能需要付出一些维护努力和额外的CPU时间(这可能是可以接受的,因为您将一次反序列化几个)。
这是使用Product只来封装产品映射的一个示例,这样您可以不必在代码库的其余部分使用记录
(ns foo
(:require
[cognitect.transit :as tr])
(:import
[com.cognitect.transit WriteHandler]
[java.io ByteArrayOutputStream]))
(defrecord Product [m])
(def product-tag "pro")
(def common-keys [:product/foo :product/bar :product/baz])
(def custom-writers
{Product (reify WriteHandler
(getVerboseHandler [_] nil)
(stringRep [_ kw] nil)
(tag [_ _] product-tag)
(rep [_ p] (let [common (mapv (:m p) common-keys)
custom (reduce dissoc (:m p) common-keys)]
(into [custom] common))))})
(def custom-readers
{product-tag (fn [rep]
(let [[m & common-vals] rep]
(merge m (zipmap common-keys common-vals))))})
(defn write [writers product]
(let [out (ByteArrayOutputStream. 4096)
wr (tr/writer out :json writers)]
(tr/write wr product)
(.toString out)))
(write {:handlers custom-writers}
(Product. {:product/foo 1 :product/bar 2 :product/baz 3 :custom/foo 4}))
;; "[\"~#pro\",[[\"^ \",\"~:custom/foo\",4],1,2,3]]"
(write {}
(Product. {:product/foo 1 :product/bar 2 :product/baz 3 :custom/foo 4}))
;; "[\"^ \",\"~:m\",[\"^ \",\"~:product/foo\",1,\"~:product/bar\",2,\"~:product/baz\",3,\"~:custom/foo\",4]]"
(write {}
{:product/foo 1 :product/bar 2 :product/baz 3 :custom/foo 4})
;; "[\"^ \",\"~:product/foo\",1,\"~:product/bar\",2,\"~:product/baz\",3,\"~:custom/foo\",4]"