From henrik at evahjelte.com Thu Dec 3 21:31:48 2009 From: henrik at evahjelte.com (Henrik Hjelte) Date: Thu, 3 Dec 2009 22:31:48 +0100 Subject: [cl-json-announce] New encoder Message-ID: <50e8e4f60912031331u4079c261j3ddd5a80c9bd1c07@mail.gmail.com> I have added a new alternative encoder to the cl-json darcs repo. I call it the "explicit" (sexp) encoder and now call the old/other (sexp) decoder the "guessing" encoder. The old "guessing" encoder is still the default, so this should not break any code. Also there is a third "streaming" encoder. In other words, flexibility. The "streaming" encoder is a way to format json to a stream. This gives you detailed control, but some of us prefer an intermediate s-exp format. The old "guessing" encoder tries to make a reasonable json representation of a lisp s-expression. For example a list becomes a json array. An a-list becomes a json object. An empty list becomes an empty json array. But some might want it to be json null. Or json false. Or an empty json literal object. With the "explicit" encoder, you give directives in the s-expression explaining exactly what json you want. This might give you more control. Also new is that you can use p-lists to output objects. Also, you can include a pre-formated json string if you wish. I have not updated the documentation, because it was autogenerated by Boris Smilga, and I don't know how to do it. Boris, can you help with this or the code to your doc-maker? There are some testcases and doc-strings explaining the use in the code, I selected one of each and put below in the mail. Also, I have found a bug with json-bind (not fixed, but I have added a testcase for it in case someone want to give it a try). Note that there is no corresponding decoder yet, simply because I have not had any egoistic reasons to add it. But it should be easy if someone want an exercise. Hope someone has a use for this, Henrik "Write the JSON representation of the list S to STREAM (or to *JSON-OUTPUT*), using one of the two rules specified by first calling USE-GUESSING-ENCODER or USE-EXPLICIT-ENCODER. The guessing encoder: If S is a list encode S as a JSON Array, if S is a dotted list encode it as an Object (per ENCODE-JSON-ALIST). The explicit decoder: If S is a list, the first symbol defines the encoding: If (car S) is 'TRUE return a JSON true value. If (car S) is 'FALSE return a JSON false value. If (car S) is 'NULL return a JSON null value. If (car S) is 'JSON princ the strings in (cdr s) to stream If (car S) is 'LIST or 'ARRAY encode (cdr S) as a a JSON Array. If (car S) is 'OBJECT encode (cdr S) as A JSON Object, interpreting (cdr S) either as an A-LIST or a P-LIST." (test explicit-encoder-complex-objects (let ((sample-1-alists `(:object (:method . some-function) (:id . 1) (:params . (:list (:object (:id . bar-id) (:name . bar)) (:true) (:list (:object (:name . a) (:id . b))) (:list (:object (:name . foo) (:id . foo-id))) )))) (sample-2-plists `(:object :method some-function :id 1 :params (:list (:json "{\"id\":\"barId\",\"name\":\"bar\"}") (:true) (:list (:object "name" a :id b)) (:list (:object :name foo :id foo-id)) ))) (correct-json " {\"method\":\"someFunction\", \"id\":1,\"params\": [{\"id\":\"barId\",\"name\":\"bar\"}, true, [{\"name\":\"a\",\"id\":\"b\"}], [{\"name\":\"foo\",\"id\":\"fooId\"}]]}") exact-json sample-1-json sample-2-json) (setf sample-1-json (with-explicit-encoder (encode-json-to-string sample-1-alists))) (setf sample-2-json (with-explicit-encoder (encode-json-to-string sample-2-plists))) (is (string= sample-1-json sample-2-json)) (setf exact-json (remove #\Newline (remove #\Space correct-json :test #'char=) :test #'char=)) (is (string= sample-1-json exact-json))))