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