Package: typedjsonrpc
typedjsonrpc is a decorator-basedJSON-RPClibrary for
Python that exposes parameter and return types. It is influenced byFlask JSON-RPCbut has some key differences:typedjsonrpc…allows return type checkingfocuses on easy debuggingThese docs are also available onRead the Docs.Using typedjsonrpcInstallationUse pip to install typedjsonrpc:$pipinstalltypedjsonrpcProject setupTo include typedjsonrpc in your project, use:fromtypedjsonrpc.registryimportRegistryfromtypedjsonrpc.serverimportServerregistry=Registry()server=Server(registry)The registry will keep track of methods that are available for JSON-RPC. Whenever you annotate
a method, it will be added to the registry. You can always use the methodrpc.describe()to get
a description of all available methods.Serveris aWSGIcompatible app that handles requests.Serveralso has a development mode that can be run usingserver.run(host, port).Example usageAnnotate your methods to make them accessible and provide type information:@registry.method(returns=int,a=int,b=int)defadd(a,b):returna+b@registry.method(returns=str,a=str,b=str)defconcat(a,b):returna+bThe return typehasto be declared using thereturnskeyword. For methods that don’t return
anything, you can use eithertype(None)or justNone:@registry.method(returns=type(None),a=str)deffoo(a):print(a)@registry.method(returns=None,a=int)defbar(a):print(5*a)You can use any of the basic JSON types:JSON typePython typestringbasestring (Python 2), str (Python 3)numberint, floatnullNonebooleanboolarraylistobjectdictYour functions may also accept*argsand**kwargs, but you cannot declare their types. So
the correct way to use these would be:@registry.method(a=str)deffoo(a,*args,**kwargs):returna+str(args)+str(kwargs)To check that everything is running properly, try (assumingaddis declared in your main
module):$curl-XPOSThttp://<host>:<port>/api-d@-<<EOF
{
    "jsonrpc": "2.0",
    "method": "__main__.add",
    "params": {
        "a": 5,
        "b": 7
    },
    "id": "foo"
}
EOF{"jsonrpc":"2.0","id":"foo","result":12}Passing any non-integer arguments intoaddwill raise aInvalidParamsError.BatchingYou can send a list of JSON-RPC request objects as one request and will receive a list of JSON-RPC
response objects in return. These response objects can be mapped back to the request objects using
theid. Here’s an example of calling theaddmethod with two sets of parameters:$curl-XPOSThttp://<host>:<port>/api-d@-<<EOF
[
    {
        "jsonrpc": "2.0",
        "method": "__main__.add",
        "params": {
            "a": 5,
            "b": 7
        },
        "id": "foo"
    }, {
        "jsonrpc": "2.0",
        "method": "__main__.add",
        "params": {
            "a": 42,
            "b": 1337
        },
        "id": "bar"
    }
]
EOF[{"jsonrpc":"2.0","id":"foo","result":12},{"jsonrpc":"2.0","id":"bar","result":1379}]DebuggingIf you create the registry with the parameterdebug=True, you’ll be able to usewerkzeug’s debugger. In that case, if there is an
error during execution - e.g. you tried to use a string as one of the parameters foradd- the
response will contain an error object with adebug_url:$curl-XPOSThttp://<host>:<port>/api-d@-<<EOF
{
    "jsonrpc": "2.0",
    "method": "__main__.add",
    "params": {
        "a": 42,
        "b": "hello"
    },
    "id": "bar"
}
EOF{"jsonrpc":"2.0","id":"bar","error":{"message":"Invalid params","code":-32602,"data":{"message":"Value 'hello' for parameter 'b' is not of expected type <type 'int'>.","debug_url":"/debug/1234567890"}}}This tells you to find the traceback interpreter at<host>:<port>/debug/1234567890.LoggingThe registry has a default logger in the moduletypedjsonrpc.registryand it logs all errors
that are not defined bytypedjsonrpc. You can configure the logger as follows:importlogginglogger=logging.getLogger("typedjsonrpc.registry")# Do configuration to this loggerHTTP status codesSince typedjsonrpc 0.4.0, HTTP status codes were added to the responses from thetypedjsonrpc.server.Serverclass. This is to improve the usage of typedjsonrpc over HTTP. The
following chart are the satus codes which are returned:ConditionBatchedStatus codeSuccessY200N200All notificationsY204N204ParseError or InvalidRequestErrorY200N400MethodNotFoundErrorY200N404All other errorsY200N500Additional featuresCustomizing type serializationIf you would like to serialize custom types, you can set thejson_encoderandjson_decoderattributes onServerto your own customjson.JSONEncoderandjson.JSONDecoderinstance. By default, we use the default encoder and decoder.Adding hooks before the first requestYou can add functions to run before the first request is called. This can be useful for some
special setup you need for your WSGI app. For example, you can register a function to print
debugging information before your first request:importdatetimefromtypedjsonrpc.registryimportRegistryfromtypedjsonrpc.serverimportServerregistry=Registry()server=Server(registry)defprint_time():now=datetime.datetime.now()print("Handling first request at:{}".format(now))server.register_before_first_request(print_time)Accessing the HTTP request from JSON-RPC methodsIn some situations, you may want to access the HTTP request from your JSON-RPC method. For example,
you could need to perform logic based on headers in the request. In thetypedjsonrpc.servermodule, there is a specialtypedjsonrpc.server.current_requestattribute which allows you to
access the HTTP request which was used to call the current method.Warningcurrent_requestis implemented as a thread-local. If you attempt to callServer.wsgi_appfromRegistry.method, thencurrent_requestwill be overriden inthat thread.Example:fromtypedjsonrpc.serverimportcurrent_request@registry.method(returns=list)defget_headers():returnlist(current_request.headers)Disabling strictness of floatstypedjsonrpcby default will only accept floats into afloattyped parameter. For example, if
your function were this:importmath@registry.method(returns=int,x=float)deffloor(x):returnint(math.floor(x))and your input were this:{
    "jsonrpc": "2.0",
    "method": "floor",
    "params": {
        "x": 1
    },
    "id": "foo"
}You would get an invalid param error like this:{
    "error": {
        "code": -32602,
        "data": {
            "debug_url": "/debug/4456954960",
            "message": "Value '1' for parameter 'x' is not of expected type <type 'float'>."
        },
        "message": "Invalid params"
    },
    "id": "foo",
    "jsonrpc": "2.0"
}This can actually frequently come up when you use a JSON encoder. A JSON encoder may choose to write
the float1.0as an integer1. In order to get around this, you can manually edit the JSON
or setstrict_floatstoFalsein yourtypedjsonrpc.registry.Registry.