JSONRPCKit is a JSON-RPC 2.0 library purely written in Swift.
// Generating request JSON
let batchFactory = BatchFactory(version: "2.0", idGenerator: NumberIdGenerator())
let request = SubtractRequest(lhs: 42, rhs: 23)
let batch = batchFactory.create(request)
batch.requestObject // ["jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": 1]
// Parsing response JSON
let responseObject: AnyObject = ["jsonrpc": "2.0", "result": 19, "id": 1]
let response = try! batch.responsesFromObject(responseObject)
response // 19 (type of response is inferred from SubtractRequest.Response)
- Swift 2.2 or 2.3
- iOS 8.0 or later
- Define request type
- Generate request JSON
- Parse response JSON
First of all, define a request type that conforms to RequestType
.
struct CountCharactersRequest: RequestType {
typealias Response = CountCharactersResponse
let characters: String
var method: String {
return "count_characters"
}
var parameters: AnyObject? {
return ["characters": characters]
}
func responseFromResultObject(resultObject: AnyObject) throws -> Response {
return try CountCharactersResponse(object: resultObject)
}
}
struct CountCharactersResponse {
let count: Int
init(object: AnyObject) throws {
enum DecodeError: ErrorType {
case MissingValueForKey(String)
}
if let count = object["count"] as? Int {
self.count = count
} else {
throw DecodeError.MissingValueForKey("count")
}
}
}
To generate request JSON, pass RequestType
instances to BatchFactory
instance, which has common JSON-RPC version and identifier generator.
When BatchFactory
instance receives request(s), it generates identifier(s) for the request(s) and request JSON by combining id, version, method and parameters.
let batchFactory = BatchFactory(version: "2.0", idGenerator: NumberIdGenerator())
let request1 = CountCharactersRequest(characters: "tokyo")
let request2 = CountCharactersRequest(characters: "california")
let batch = batchFactory.create(request1, request2)
The request JSON is available in batch.requestObject
. It looks like below:
[
{
"jsonrpc" : "2.0",
"method" : "count_characters",
"id" : 1,
"params" : {
"characters" : "tokyo"
}
},
{
"jsonrpc" : "2.0",
"method" : "count_characters",
"id" : 2,
"params" : {
"characters" : "california"
}
}
]
Suppose that following JSON is returned from server:
[
{
"jsonrpc" : "2.0",
"id" : 1,
"result" : {
"count" : 5
}
},
{
"jsonrpc" : "2.0",
"id" : 2,
"result" : {
"count" : 10
}
}
]
To parse response object, execute responsesFromObject(_:)
of BatchType
instance.
When responsesFromObject(_:)
is called, BatchType
finds corresponding response object by comparing request id and response id.
After it find the response object, it executes responsesFromObject(_:)
of Response
to get Request.Response
from the response object.
let responseObject = ...
let (response1, response2) = try! batch.responsesFromObject(responseObject)
print(response1) // CountCharactersResponse(count: 5)
print(response2) // CountCharactersResponse(count: 10)
JSON-RPC over HTTP by APIKit
APIKit is a type-safe networking abstraction layer.
APIKit also has RequestType
that represents HTTP request.
import APIKit
struct MyServiceRequest<Batch: BatchType>: APIKit.RequestType {
typealias Response = Batch.Responses
let batch: Batch
var baseURL: NSURL {
return NSURL(string: "https://api.example.com/")!
}
var method: HTTPMethod {
return .POST
}
var path: String {
return "/"
}
var parameters: AnyObject? {
return batch.requestObject
}
func responseFromObject(object: AnyObject, URLResponse: NSHTTPURLResponse) throws -> Response {
return try batch.responsesFromObject(object)
}
}
let batchFactory = BatchFactory(version: "2.0", idGenerator: NumberIdGenerator())
let request1 = CountCharactersRequest(message: "tokyo")
let request2 = CountCharactersRequest(message: "california")
let batch = batchFactory.create(request1, request2)
let httpRequest = MyServiceRequest(batch: batch)
Session.sendRequest(httpRequest) { result in
switch result {
case .Success(let response1, let response2):
print(response1.count) // CountCharactersResponse
print(response2.count) // CountCharactersResponse
case .Failure(let error):
print(error)
}
}
git diff 0.6.0 develop/1.0 -- Example
JSONRPCKit is released under the MIT License.