3

这个问题实际上是关于我对重新启动缺乏了解。

在编码器中cl-json存在一个我想使用的诱人宏

with-substitute-printed-representation-restart

但可惜我不太明白怎么做。

这个

(cl-json::encode-json-plist (list :boo "boo" :foo "foo"))

返回

{"boo":"boo","foo":"foo"}

这个

(cl-json::encode-json-plist (list :boo "boo" :foo  (lambda (a b) (+ a b))))

发出 UNENCODABLE-VALUE-ERROR 信号

我想从 cl-json 找到函数的那一点重新开始,并让它在遇到我包含在列表中的添加 lambda 时返回我选择的内容。

(defun my-func ()
 (handler-bind ((cl-json::UNENCODABLE-VALUE-ERROR 
                #'(lambda (e) (invoke-restart 'return-default))))
   (myencode (list :boo "boo" :foo (lambda (a b) (+ a b))))
 )
)

(defun myencode (alist)
 (restart-case
  (cl-json::encode-json-plist-to-string alist)
  (return-default () :report "Just return a default could not do this string" "barf")
 )
)

返回“barf”

我希望它返回

{"boo":"boo","foo":"barf"}

我该如何使用该宏来做到这一点?换句话说,我希望在引发错误的地方而不是在捕获错误的地方重新启动。我可以这样做吗?

4

1 回答 1

1

我不明白文档是否有误,或者我的代码读得不好,但是当无法对对象进行编码时,应该已经可以重新启动。如果您按如下方式重新定义cl-json了默认方法,那么您将重新启动。encode-json

(defmethod encode-json (anything &optional (stream *json-output*))
  "If OBJECT is not handled by any specialized encoder signal an error
which the user can correct by choosing to encode the string which is
the printed representation of the OBJECT."
  (with-substitute-printed-representation-restart (anything stream)
    (unencodable-value-error anything 'encode-json)))

顺便说一句,您可以重新定义,以便重新启动接受一个参数,而不是打印字符串:

(defmethod encode-json (anything &optional (stream *json-output*))
  "If OBJECT is not handled by any specialized encoder signal an error
which the user can correct by choosing to encode the string which is
the printed representation of the OBJECT."
  (with-substitute-printed-representation-restart (anything stream)
    (restart-case (unencodable-value-error anything 'encode-json)
      (use-value (v)
        :report "Use a different encoding"
        (check-type v string)
        (write v :stream stream :escape t)))))

例如:

CL-USER> (handler-bind
                ((json:unencodable-value-error
                  (lambda (err)
                    (declare (ignore err))
                    (invoke-restart 'use-value "UNKNOWN"))))
              (json:encode-json
               `(((foo . ,#'print) (bar . "baz")))))
[{"foo":"UNKNOWN","bar":"baz"}]

您可能想直接询问图书馆的作者

于 2020-10-02T18:49:48.910 回答