如何在Clojure中对Exception对象进行JSON编码?
解决Clojure中Exception对象无法JSON编码的问题
我之前也碰到过一模一样的情况——直接把Exception对象丢给JSON编码器肯定会失败,因为默认的JSON库(比如Cheshire)不知道怎么序列化Java/Clojure的异常实例,尤其是clojure.lang.ExceptionInfo这种自带额外数据的类型。咱们可以通过把异常转换成普通的Clojure Map来解决这个问题,这样JSON编码器就能轻松处理了。
步骤1:编写异常转Map的工具函数
先写一个函数,把Throwable(包括Exception和ExceptionInfo)转换成包含关键信息的Map,既保留日志需要的内容,又能被JSON正常序列化:
(defn exception->map [^Throwable ex] (merge {:message (.getMessage ex) :exception-class (.getName (.getClass ex)) :stack-trace (map str (.getStackTrace ex))} ;; 如果是ExceptionInfo,额外添加它的自定义data字段 (when (instance? clojure.lang.ExceptionInfo ex) {:data (ex-data ex)})))
这个函数会提取异常的核心信息:
message:异常的描述文本exception-class:异常类的全名,方便快速定位问题类型stack-trace:把栈轨迹数组转成字符串列表,便于查看完整调用链- 针对
ExceptionInfo,还会带上它自带的业务自定义数据
步骤2:修改异常处理器
把原来的异常处理器里直接传入ex的地方,换成用上面的函数转换成Map:
(defn exception-handler "Handles exceptions." [f] (fn [^Exception ex data request] (let [error-details (exception->map ex)] (log/error (json/generate-string {:request-id log-helper/*request-id* :error error-details}))) (f (.getMessage ex))))
这样修改后,json/generate-string处理的就不再是异常对象,而是一个普通的Clojure Map,自然就能正常生成JSON了。
额外说明
如果你的项目用Cheshire作为JSON库,也可以自定义编码器直接处理Throwable,但把异常转换成Map的方式更直观,兼容性也更好——不管用哪个JSON库,都能正常处理这种普通数据结构。生成的JSON日志推到Sumologic后,你就能直接根据error.exception-class、error.message或者error.data里的字段来过滤和解析日志了。
内容的提问来源于stack exchange,提问作者Freid001
相关产品推荐
相关产品推荐

