问题
在编写json时,我想要在每个写入调用的基础上设置一个回退函数,当没有其他JSONWriter实现可以处理该类型时调用(例如,在这里调用我的函数而不是抛出异常 此处)。
一个设置每个写入调用的回退函数的示例用例是日志记录。在记录JSON时,大多数时候,您最希望不抛出日志执行和序列化异常。如果你抛出异常,你会丢失信息,并且掩盖实际的错误。因此,当记录JSON,并且遇到没有JSONWriter实现的对象时,简单地调用str
很有帮助,而不是抛出异常。在这个用例中,一个重要的部分是你事先不知道传递进来的对象类型。
提议的解决方案
向write
添加一个选项:default-fn
来处理默认情况。该函数将使用3个参数调用x
,out
和options
,并预计它会以任意的形式将x
打印到out
。在write-generic
中为x
不是数组的情况调用该:default-fn
函数(请参见此处代码)。将把:default-fn
的默认设置添加到default-write-options
此处。默认设置的行为与当前实现完全相同——抛出异常。
(defn default-default-fn
[x out options]
(throw (Exception. (str "Don't know how to write JSON of " (class x)))))
此方案影响最小,并且是一个增量更改。它允许用户传递一个回退函数来写入无法处理的对象,而不需要对全局状态进行修改等。
其他潜在解决方案
- data.json不允许用户控制任何默认对象如何编码。一个影响更大的更改则是允许用户自定义所有或任何默认的编码方式。这样规模的变化将需要对如何有效地执行进行更多研究,例如别人是如何做的等。
当前解决方案
目前唯一的选择是全局覆盖JSONWriter的Object扩展,以调用我的函数,而不是内置函数。这有一个缺点,那就是它是一个全局覆盖——并非所有使用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})