On 5 Jun 2011, at 23:47, Nicolas Martyanoff wrote:
The following form breaks when evaluated:
(json:encode-json-to-string '((:a . ((:b . ((:c . 42)))))))
Help! 11 nested errors. SB-KERNEL:*MAXIMUM-ERROR-DEPTH* exceeded.
Hello. That's expected behaviour (sort of).
Essentially, when ENCODE-JSON is passed a cons cell, it has no way of telling whether the cell is the head of A) an alist (which should be encoded as a JSON Object), or B) of a proper list which is not an alist (which should be encoded as a JSON Array), or C) of an improper list (which is unencodable and so should produce an error). So it tries the option B first, and, if that fails, the option A. In your case, this situation is reproduced on every level of nesting. The problem is that SB-KERNEL:*MAXIMUM-ERROR-DEPTH* is quite shallow by default (10), and the try-proper-list-fall-back-to-alist approach results in a layering of nested conditions which is deeper than that number. Writing, e. g.,
(let ((sb-kernel:*maximum-error-depth* 20)) (json:encode-json-to-string '((:a . ((:b . ((:c . 42))))))))
produces the correct result, "{"a":{"b":{"c":42}}}" .
I know this is not a sustainable approach, but at this moment I have no good idea how to modify CL-JSON to get around this issue. Your best options at this moment would be to use either CLOS objects instead of alists, or the explicit encoder from the repository version:
(json:with-explicit-encoder (json:encode-json-to-string '(:object :a (:object :b (:object :c 42)))))
or
(json:with-explicit-encoder (json:encode-json-to-string '(:object (:a . (:object (:b . (:object (:c . 42))))))))
Sincerely, - B. Smilga.