Continuing to work on my CL-JSON based JSON-RPC server, I am concerned about the fact that we translate NIL -> null.
If a CL function returns NIL, and the return value is simply encoded into the JSON return package, then we get a message that /should/ indicate an error, according to the JSON-RPC server.
In fact, if our CL function is invoked by JSON-RPC, then we really should have NIL either encoded as [] or as false, but /never/ as null.
Any ideas about how we should modify invoke-rpc-parsed to fix this?
What is the right way to tell CL-JSON to encode a false?
Thanks, R
On Thu, Dec 31, 2009 at 11:17 PM, Robert Goldman rpgoldman@sift.info wrote:
Continuing to work on my CL-JSON based JSON-RPC server, I am concerned about the fact that we translate NIL -> null.
If a CL function returns NIL, and the return value is simply encoded into the JSON return package, then we get a message that /should/ indicate an error, according to the JSON-RPC server.
In fact, if our CL function is invoked by JSON-RPC, then we really should have NIL either encoded as [] or as false, but /never/ as null.
Any ideas about how we should modify invoke-rpc-parsed to fix this?
What is the right way to tell CL-JSON to encode a false?
Cl-json currently has three encoders. Traditionally the most used and the one used in json-rpc is the guessing encoder (see testcases for documentation). It is not very good if you want fine-grained control, then I'd say that the explicit encoder I recently added is more convenient. Another alternative is the streaming encoder. With the explicit encode json false is (false)
To fix this, I'd probably add an option to (or even recode) json-rpc to use the explicit-encoder instead. Preferably backwards compatible so code that uses json-rpc and uses the guessing-encoder doesn't break. Maybe a function called defun-json-rpc-explicit? The backward compatiblity could be preserved by encoding the old defun-json-rpc using the guessing encoder, then passing it as a json-string to the explicit encoder using the (json "some json string") format. I think this sounds more job than it is, it should not be very difficult.
/Henrik
On 1/1/10 Jan 1 -10:36 AM, Henrik Hjelte wrote:
On Thu, Dec 31, 2009 at 11:17 PM, Robert Goldman rpgoldman@sift.info wrote:
Continuing to work on my CL-JSON based JSON-RPC server, I am concerned about the fact that we translate NIL -> null.
If a CL function returns NIL, and the return value is simply encoded into the JSON return package, then we get a message that /should/ indicate an error, according to the JSON-RPC server.
In fact, if our CL function is invoked by JSON-RPC, then we really should have NIL either encoded as [] or as false, but /never/ as null.
Any ideas about how we should modify invoke-rpc-parsed to fix this?
What is the right way to tell CL-JSON to encode a false?
Cl-json currently has three encoders. Traditionally the most used and the one used in json-rpc is the guessing encoder (see testcases for documentation). It is not very good if you want fine-grained control, then I'd say that the explicit encoder I recently added is more convenient. Another alternative is the streaming encoder. With the explicit encode json false is (false)
To fix this, I'd probably add an option to (or even recode) json-rpc to use the explicit-encoder instead. Preferably backwards compatible so code that uses json-rpc and uses the guessing-encoder doesn't break. Maybe a function called defun-json-rpc-explicit? The backward compatiblity could be preserved by encoding the old defun-json-rpc using the guessing encoder, then passing it as a json-string to the explicit encoder using the (json "some json string") format. I think this sounds more job than it is, it should not be very difficult.
What about making the type argument to defun-json-rpc optional instead of mandatory. If the default is explicit encoding then we'd still have backward compatibility without adding a new, more verbose-named defun?
The CL-JSON spec for 1.1 seems like a real mess --- it's not at all clear what should happen if you invoke a method over CL-JSON that returns a null value (e.g., a JS function with no return).
The 2.0 (draft) spec seems to have a much clearer approach to this....
I'm inclined to just move to observing the draft 2.0 spec.
Best, r
What about making the type argument to defun-json-rpc optional instead of mandatory. If the default is explicit encoding then we'd still have backward compatibility without adding a new, more verbose-named defun?
yes, good idea. I had actually forgotten I had added some support for different encoders in json-rpc.
I think the reason I don't had the type argument optional is because I am a weak coder, I just don't know how to make type &optional in the right way. I guess you can put all three type lambda-list and body as one &rest and parse it. On the other hand: I personally don't have a strong problem with breaking backwards compatibilty in this way, it is only for a small subset of cl-json and it breaks you old code in an "nice" way, throwing an error that is easy to fix.
(defmacro defun-json-rpc (name type lambda-list &body body)
The CL-JSON spec for 1.1 seems like a real mess --- it's not at all clear what should happen if you invoke a method over CL-JSON that returns a null value (e.g., a JS function with no return).
The 2.0 (draft) spec seems to have a much clearer approach to this....
I'm inclined to just move to observing the draft 2.0 spec.
Yes why not? I am not aware of the exact differences, except that 2.0 has named parameters.
Maybe it is possible to expose a function both as 1.1 and 2.0?
/Henrik
I have most of a patch for providing JSON-RPC 2.0 support. I will try to submit it by the end of the week.
What about a json-rpc type of :Boolean? This would take the raw output of the cl function and turn it into true or false according to cl rules. We could also have a type of :array as alternative, that would turn any sequence into a json array and would turn NIL into [] (singleton return values would signal an error).
Just a thought; haven't considered the implications deeply...
On Jan 6, 2010, at 7:10, Henrik Hjelte henrik@evahjelte.com wrote:
What about making the type argument to defun-json-rpc optional instead of mandatory. If the default is explicit encoding then we'd still have backward compatibility without adding a new, more verbose-named defun?
yes, good idea. I had actually forgotten I had added some support for different encoders in json-rpc.
I think the reason I don't had the type argument optional is because I am a weak coder, I just don't know how to make type &optional in the right way. I guess you can put all three type lambda-list and body as one &rest and parse it. On the other hand: I personally don't have a strong problem with breaking backwards compatibilty in this way, it is only for a small subset of cl-json and it breaks you old code in an "nice" way, throwing an error that is easy to fix.
(defmacro defun-json-rpc (name type lambda-list &body body)
The CL-JSON spec for 1.1 seems like a real mess --- it's not at all clear what should happen if you invoke a method over CL-JSON that returns a null value (e.g., a JS function with no return).
The 2.0 (draft) spec seems to have a much clearer approach to this....
I'm inclined to just move to observing the draft 2.0 spec.
Yes why not? I am not aware of the exact differences, except that 2.0 has named parameters.
Maybe it is possible to expose a function both as 1.1 and 2.0?
/Henrik
On 1/6/10 Jan 6 -7:46 AM, Robert P. Goldman wrote:
I have most of a patch for providing JSON-RPC 2.0 support. I will try to submit it by the end of the week.
What about a json-rpc type of :Boolean? This would take the raw output of the cl function and turn it into true or false according to cl rules. We could also have a type of :array as alternative, that would turn any sequence into a json array and would turn NIL into [] (singleton return values would signal an error).
A quick follow-up: would it be acceptable to create a generic function like this:
(defgeneric encode-json-rpc-value (keyword value) (:documentation "An extensible set of methods for encoding JSON-RPC values according to a keyword specification") (:method (keyword value) (declare (ignore value)) (error "Keyword ~a does not correspond to any JSON-RPC encoding" keyword)) (:method ((keyword (eql :guessing) value) ....))
and use this to replace the ecase in INVOKE-RPC-PARSED ?
That would make it easier for people to come up with their own encoding schemes.
If you like, I will try to supply a patch.
best, r
Just a thought; haven't considered the implications deeply...
On Jan 6, 2010, at 7:10, Henrik Hjelte henrik@evahjelte.com wrote:
What about making the type argument to defun-json-rpc optional instead of mandatory. If the default is explicit encoding then we'd still have backward compatibility without adding a new, more verbose-named defun?
yes, good idea. I had actually forgotten I had added some support for different encoders in json-rpc.
I think the reason I don't had the type argument optional is because I am a weak coder, I just don't know how to make type &optional in the right way. I guess you can put all three type lambda-list and body as one &rest and parse it. On the other hand: I personally don't have a strong problem with breaking backwards compatibilty in this way, it is only for a small subset of cl-json and it breaks you old code in an "nice" way, throwing an error that is easy to fix.
(defmacro defun-json-rpc (name type lambda-list &body body)
The CL-JSON spec for 1.1 seems like a real mess --- it's not at all clear what should happen if you invoke a method over CL-JSON that returns a null value (e.g., a JS function with no return).
The 2.0 (draft) spec seems to have a much clearer approach to this....
I'm inclined to just move to observing the draft 2.0 spec.
Yes why not? I am not aware of the exact differences, except that 2.0 has named parameters.
Maybe it is possible to expose a function both as 1.1 and 2.0?
/Henrik
cl-json-devel mailing list cl-json-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/cl-json-devel