2024 年 Clojure 状态调查! 中分享您的想法。

欢迎!请查看 关于 页面以获取更多关于此功能的信息。

+2
data.json
重新标记

在内部,`clojure.data.json/write` 在遇到非顶级命名形式的 `clojure.lang.Named` 实例时会调用 `name`,这将去除命名空间

(json/write {:foo/bar :baz/bork}
            *out*
            :escape-slash false)
;; => {"bar":"bork"}

clojure.data.json/write 函数提供了 :key-fn:value-fn 选项来改变这种行为(或任何其他行为),在映射键和值上

(json/write {:foo/bar :baz/bork}
            *out*
            :escape-slash false
            :key-fn (comp str symbol)
            :value-fn (fn [k v] (if (instance? clojure.lang.Named v)
                                  (str (symbol v))
                                  v)))
;; => {"foo/bar":"baz/bork"}

但这在其他上下文中不起作用(根据文档字符串,这并不是预期行为)

(json/write {:foo/bar [:baz/bork]}
            *out*
            :escape-slash false
            :key-fn (comp str symbol)
            :value-fn (fn [k v] (if (instance? clojure.lang.Named v)
                                  (str (symbol v))
                                  v)))
;; => {"foo/bar":["bork"]}

改变此行为在所有上下文中的唯一机制是扩展 `JSONWriter` 协议,但这将全局改变行为。如果有一个选项可以在所有上下文中保留命名空间,或者覆盖给定类型的写入方式而不全局改变它,那将会很有帮助。


编辑
我刚好也遇到了相同的问题。

我也担心覆盖默认行为,以防某些其他库(例如 Datomic Cloud)依赖它。

尽管如此,我已经基于默认实现尝试进行覆盖,至今还没有遇到任何问题。

    (defn- write-named [x out options]
      (json/-write (kw->sym->str x) out options))
    
    (extend clojure.lang.Named json/JSONWriter {:-write write-named})

我想,我会把这个例子放在这里供不太熟悉 Clojure 协议的人参考。
希望这是正确的做法 :)

2 个答案

+1

https://clojure.atlassian.net/browse/DJSON-54的注释中提到了您提到的功能。正如Alex在其注释中所述,您的提议是一个较大的更改,需要提前进行一些设计工作。话虽如此,我认为您的提议值得探究,我们可以在那个条目上继续讨论。

我已经解决了这个即时需求(原来我使用`:value-fn`错误,它足够满足我的当前需求),因此除非我的需求改变(这并非不可能),否则我不太可能个人参与那个讨论。我提出这个请求是因为Alex要求我这么做。
0
...