问题
在编写json时,我想要为每个写入调用设置一个回退函数,以便在没有其他JSONWriter实现可以处理该类型(例如,调用我的函数这里而不是抛出异常)时使用该值。
设置每个写入的基本回退函数的一个使用实例是日志记录。当记录JSON时,通常你希望尽力避免日志执行和序列化时抛出异常。如果您抛出异常,就会丢失信息,并模糊实际错误。因此,当记录JSON且遇到没有JSONWriter实现的对象时,简单地对该对象调用str
,而不是抛出异常是有帮助的。这个用例的一个重要部分是,您不知道可能传入的对象的类型。
建议的解决方案
向write
添加一个选项:default-fn
以处理默认情况。此函数将使用3个参数x
、out
和options
进行调用,并期望以任何方式将x
打印到out
。当x
不是数组时,会在write-generic
中调用:default-fn
函数(见代码)。将默认设置添加到default-write-options
(见这里)以设置:default-fn
的默认值。默认设置将完全按当前实现的方式抛出异常。
(defn default-default-fn
[x out options]
(throw (Exception. (str "Don't know how to write JSON of " (class x)))))
此解决方案最小化了侵入性,并且是增量的更改。它允许用户在无需修改全局状态的情况下传递回退函数以处理未处理的对象。
其他潜在解决方案
- data.json不允许用户控制任何默认对象的编码方式。一个更具侵入性和较大的改变是允许用户自定义如何编舞任何或所有默认对象。这种规模的变化将需要对如何高效做到这一点、其他人如何做等进行更多研究。
当前解决方案
目前唯一的选项是全局覆盖JSONWriter的对象扩展以调用自己的函数,而不是内置函数。此操作的缺点是它是全局覆盖的 -- 并非所有使用data.json的jvm用户都希望将其特殊操作设置为默认值。
(defn my-custom-json-write-generic [x out options]
(if (.isArray (class x))
(json/-write (seq x) out options)
(do-my-special-thing x out options)))
(extend java.lang.Object json/JSONWriter {:-write my-custom-json-write-generic})