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