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 投票
...