JSON-RPCUser Guide
Overview
An implementation of the JSON-RPC v2.0 specification.
JSON-RPC is used by the Language Server Protocol (LSP) to serialise messages.
Use JSON-RPC to invoke methods on a class instance.
Quick Start
using afJsonRpc
class Example {
Void main() {
sink := ExampleSink() // this will receive the method calls
jsonRpc := JsonRpc(sink)
// rpc call with positional parameters
res1 := jsonRpc.call(
"""{
"jsonrpc": "2.0",
"id" : 1,
"method" : "subtract",
"params" : [42, 23]
}""".in
)
echo(res1)
// <-- {"jsonrpc": "2.0", "result": 19, "id": 1}
// rpc call with named parameters
res2 := jsonRpc.call(
"""{
"jsonrpc": "2.0",
"id" : 3,
"method" : "subtract",
"params" : {"subtrahend": 23, "minuend": 42}
}""".in
)
echo(res2)
// <-- {"jsonrpc": "2.0", "result": 19, "id": 3}
}
}
class ExampleSink {
Float subtract(Float minuend, Float subtrahend) {
return minuend - subtrahend
}
}
Multiple Sinks
For larger RPC implementations you will want multiple sinks for your methods. For this, pass a Str:Obj map to JsonRpc where the Objs are the sinks, and the Strs are a matching prefix.
jsonRpc := JsonRpc([
"text/" : TextSink()
"image/" : ImageSink()
])
Then the RPC call {"jsonrpc": "2.0", "method": "text/update"} would be forwarded to the method TextSink.update().
And the RPC call {"jsonrpc": "2.0", "method": "image/update"} would be forwarded to the method ImageSink.update().
For optimised calls, use a custom dispatchFn:
JsonRpc(..., [
"dispatchFn" : JsonRpc.multiSinkDispatchFn('/')
])
Transport over HTTP
Use afBedSheet to create a HTTP server for receive your RPC calls.
JSON to Fantom object mapping
Use afJson to map JSON to Fantom objects.
json := afJson::JsonConverters()
jsonRpc := JsonRpc(..., [
"invokeFn" : JsonRpc.convertingInvokeFn |type, val| {
type != null ? json.fromJsonVal(val, type) : json.toJsonVal(val)
}
])