Migration¶
From 4.x to 5.x¶
Version 5 changed how methods report their result. Most other code needs only small changes.
Old methods fail with no details
In 4.x a method returned its result directly. In 5.x it must return
Success(result). A 4.x method such as
@method
def ping():
return "pong"
still runs, but the client gets a -32603 "Internal error". Up to 5.0.9,
its data says "The method did not return a valid Result". From 5.0.10
the client gets no details, and the log says what's wrong:
Method 'ping' returned 'pong', which is not a Result, so the client got an Internal error. Return Success(value) or Error(code, message). ...
If you don't see that line, configure logging (see
Errors and logging). Then search your code for
return statements in methods. mypy and pyright catch them too, once
methods are annotated -> Result (see Typing).
A method, before and after¶
4.x:
# jsonrpcserver 4.x. This doesn't work on 5.x.
from jsonrpcserver import dispatch, method
from jsonrpcserver.exceptions import ApiError, InvalidParamsError
@method
def divide(a, b):
if not isinstance(b, (int, float)):
raise InvalidParamsError("b must be a number")
if b == 0:
raise ApiError("Can't divide by zero", code=1)
return a / b
response = dispatch(request_body)
if response.wanted:
send(str(response), status=response.http_status)
5.x:
from jsonrpcserver import Error, InvalidParams, Result, Success, dispatch, method
@method
def divide(a: float, b: float) -> Result:
if not isinstance(b, (int, float)):
return InvalidParams("b must be a number")
if b == 0:
return Error(1, "Can't divide by zero")
return Success(a / b)
response = dispatch('{"jsonrpc": "2.0", "method": "divide", "params": [1, 0], "id": 1}')
print(response, 200 if response else 204)
{"jsonrpc": "2.0", "error": {"code": 1, "message": "Can't divide by zero"}, "id": 1} 200
What changed¶
| 4.x | 5.x |
|---|---|
return value |
return Success(value) |
raise ApiError(message, code=1, data=...) |
return Error(code, message, data), or raise JsonRpcError(code, message, data). Note the order: code first. |
raise InvalidParamsError(...) |
return InvalidParams(data) |
raise MethodNotFoundError |
there's no equivalent. jsonrpcserver sends "Method not found" itself |
dispatch returns a Response object |
dispatch returns a string. dispatch_to_serializable gives a dict |
str(response) |
response is already the string |
response.wanted |
if response:, since a notification gives "" |
response.http_status |
200 if response else 204. Errors are sent with 200 too |
methods = Methods(ping, add), methods.add(...) |
a plain dict, {"ping": ping, "add": add}, or @method |
dispatch(..., serialize=..., deserialize=...) |
serializer= and deserializer= |
convert_camel_case=True |
removed. Name your methods and parameters as clients call them |
basic_logging=True, trim_log_values=True |
removed. Configure the jsonrpcserver logger yourself |
a .jsonrpcserverrc config file |
removed. Pass options to dispatch |
debug=True |
removed in 5.0.0, so 5.0.0 to 5.0.9 always send exception messages to the client. Back in 5.0.10, where it works as in 4.x: off by default |
Code written for 4.x that 5.x can't run gives clear errors in most cases. The
removed keywords raise TypeError, and response.wanted raises
AttributeError: 'str' object has no attribute 'wanted'. The plain return
value above is the one that fails quietly, and str(response) still works but
is no longer needed.
The 4.x documentation is no longer online. The changelog lists every 4.x change.
From 5.0.9 to 5.0.10¶
Most code needs no change. These are the differences you might notice.
Exception messages are no longer sent. A method that raises an exception
it doesn't catch gives a -32603 "Internal error" with no data. Clients that
read error.data for those errors get nothing now. The exception is logged.
Pass debug=True in development to get the message back in the response. See
Security.
Custom validators see one request at a time. In a batch, the validator
is called once for each request, with just that request. In 5.0.9 it was
called once with the whole list. A validator that enforced a rule about the
whole batch, such as a size limit, silently stops doing it. Use
max_batch_size instead. See Validation.
Batches are handled per request. A batch that mixes valid and invalid requests used to get one "Invalid request" for the whole batch. Now each invalid request gets its own error, and the valid ones run. See Notifications and batches.
NaN and Infinity give an error. A result that contains NaN, Infinity
or -Infinity now gives an Internal error, because they aren't valid JSON. To
send them anyway, pass serializer=json.dumps.
A result that can't be serialized gives an error. For example a
datetime. In 5.0.9 dispatch raised TypeError. Now that response becomes
an Internal error, the error is logged, and the rest of a batch is sent.
New warnings. Error and JsonRpcError warn when the code isn't an
integer or the message isn't a string, and @method warns about names that
start with rpc.. The responses are the same as before. If your tests turn
warnings into errors, fix the code or the names. See
Errors and logging.
Deprecated names. In jsonrpcserver.response, serialize_error,
serialize_success and to_serializable_one give a DeprecationWarning. Use
to_error_dict, to_success_dict and to_dict. ResponseType is kept, but
use Response. They will be removed in 6.0.
New loggers and log lines. A serializer failure is logged on
jsonrpcserver.main, and serve() logs where it's listening. A method that
returns a plain value is logged with a hint instead of a traceback. See
Errors and logging.
Plain methods work with async_dispatch. In 5.0.9 they gave an Internal
error.
serve() sends 204 for a notification, instead of 200 with an empty
body, and answers bad requests instead of dropping the connection.
New features you can use: max_batch_size and debug on every dispatch
function, jsonrpcserver.__version__, and type checking that sees through
@method (see Typing).
Python 3.8 or later. 5.0.10's package metadata says so, so older Pythons keep installing 5.0.9.