I created this patch before I got your email. What my usage is now the following:
(let ((json:*json-identifier-name-to-lisp* 'identity)
(json:*json-symbolize-lisp-key* 'identity))
(json:decode-json-from-string json))
The patch is attached:
I have not taken the time to read through how the accumulator works. This approach modifies the default behavior in a more fine-grained way.
On 25 Jun 2009, at 22:27, Red Daly wrote:Indeed, thank you for pointing this out.
CL-JSON does not allow the user to customize the means used to decode the keys for object literals. It may be important to avoid interning in a web setting, for example, since interns of many unique symbols could potentially use a lot of memory. An attack could exploit this by submitting something that is passed through cl-json that has many very large, unique symbols.
There used to be a way to get around this with the factory method customization, but the current library does not include a means of changing the decoding behavior for a key to avoid interning it. [...]
It is the same thing in the new version, except that customization works in a somewhat different way. Broadly speaking, you have to redefine the way a level of JSON Object structure is accumulated to form the corresponding Lisp structure. E. g., in the following example new (KEY . VALUE) pairs are clipped onto the end of a list accumulator, to form an alist:
(defvar *accumulator* nil)
(defvar *accumulator-last* nil)
(defun init-accumulator ()
(setq *accumulator* (cons nil nil)
*accumulator-last* *accumulator*))
(defun collect-key (key)
(setq *accumulator-last*
(setf (cdr *accumulator-last*)
(cons (cons key nil) nil))))
(defun collect-value (value)
(setf (cdar *accumulator-last*) value))
(defun accumulator-get-value ()
(cdr *accumulator*))
(json:bind-custom-vars
(:beginning-of-object #'init-accumulator
:object-key #'collect-key
:object-value #'collect-value
:end-of-object #'accumulator-get-value
:object-scope '(*accumulator* *accumulator-last*))
(json:decode-json-from-string
"{\"foo\": [{\"bar\": \"xyzzy\"}, {\"baz\": true}],
\"quux\": 123}"))
=> (("foo" (("bar" . "xyzzy")) (("baz" . T))) ("quux" . 123))
[...] Unless I am missing something, could this functionality be added?
No problem, but could you maybe provide a sample of phantasy code which showed how this kind of customization interface should look from the user's side? With that, we'll be more able to meet your expectations. (I cannot, of course, guarantee that your interface shall be reproduced 100% exactly, rather it'll serve as a guideline.)
Yours,
- B. Smilga.