Clojure Transit序列化嵌套元数据的实现方法咨询
在Transit中完整保留并还原Clojure嵌套结构的元数据
Transit默认不会序列化Clojure对象的元数据,要保留嵌套结构里的所有元数据,需要自定义Transit的读写处理器,将元数据和对象内容绑定后序列化,再在读取时还原。
实现步骤与代码示例
1. 自定义写处理器(序列化时保留元数据)
将带元数据的对象(所有实现clojure.lang.IObj的类型,包括向量、列表等)转换成包含元数据和实际内容的结构,用自定义类型标识标记:
(require '[cognitect.transit :as transit]) (require '[clojure.java.io :as io]) ; 写处理器:识别带元数据的对象,将其转为{:meta 元数据, :value 实际内容}的结构 (def write-handlers {clojure.lang.IObj (transit/write-handler (constantly "with-meta") ; 自定义类型标识,读写端需一致 (fn [obj] {:meta (meta obj) :value obj}))}) ; 封装序列化函数 (defn serialize-with-meta [data output-stream] (let [writer (transit/writer output-stream :json {:handlers write-handlers})] (transit/write writer data)))
2. 自定义读处理器(反序列化时还原元数据)
识别自定义的"with-meta"类型,将元数据重新绑定到对象上:
; 读处理器:解析"with-meta"类型,还原元数据 (def read-handlers {"with-meta" (transit/read-handler (fn [{:keys [meta value]}] (with-meta value meta)))}) ; 封装反序列化函数 (defn deserialize-with-meta [input-stream] (let [reader (transit/reader input-stream :json {:handlers read-handlers})] (transit/read reader)))
3. 测试验证
用带嵌套元数据的结构测试序列化与反序列化:
; 构造带嵌套元数据的测试结构 (def test-data (with-meta [:S (with-meta [:AB (with-meta [:A "a"] #:instaparse.gll{:start-index 0, :end-index 1}) (with-meta [:B "b"] #:instaparse.gll{:start-index 1, :end-index 2})] #:instaparse.gll{:start-index 0, :end-index 2})] #:instaparse.gll{:start-index 0, :end-index 2})) ; 序列化到字节流 (def out-stream (java.io.ByteArrayOutputStream.)) (serialize-with-meta test-data out-stream) ; 反序列化 (def in-stream (java.io.ByteArrayInputStream. (.toByteArray out-stream))) (def restored-data (deserialize-with-meta in-stream)) ; 验证元数据是否完整保留 (meta restored-data) ; => #:instaparse.gll{:start-index 0, :end-index 2} (meta (second restored-data)) ; => #:instaparse.gll{:start-index 0, :end-index 2} (meta (first (second (second restored-data)))) ; => #:instaparse.gll{:start-index 0, :end-index 1}
注意事项
- 如果仅需要处理向量而非所有带元数据的对象,可将写处理器的键换成
clojure.lang.PersistentVector,缩小处理范围。 - 若元数据包含自定义复杂类型,需额外为这些类型添加Transit读写处理器,确保其能被正确序列化。
- 自定义类型标识(如示例中的"with-meta")需在读写端保持一致,否则无法正确解析。
内容的提问来源于stack exchange,提问作者judep
相关产品推荐
相关产品推荐

