json rpc implementation in swift

To implement JSON-RPC in Swift, you can use the Codable protocol to map the JSON request and response to Swift structs or classes. You will also need to send HTTP POST requests to the server to invoke the remote methods.

Here's an example implementation of a JSON-RPC client in Swift:

main.swift
import Foundation

struct JsonRpcRequest: Encodable {
    let id: Int
    let method: String
    let params: [String: Any]?
    let jsonrpc = "2.0"
}

struct JsonRpcResponse<Result: Decodable>: Decodable {
    let id: Int
    let result: Result?
    let error: JsonRpcError?
    let jsonrpc: String
}

struct JsonRpcError: Decodable {
    let code: Int
    let message: String
}

class JsonRpcClient {
    
    private let url: URL
    
    init(url: URL) {
        self.url = url
    }
    
    func sendRequest<T: Decodable>(method: String, params: [String: Any]? = nil, completion: @escaping (T?, Error?) -> Void) {
        let id = Int(Date().timeIntervalSince1970 * 1000)
        let request = JsonRpcRequest(id: id, method: method, params: params)
        
        guard let jsonData = try? JSONEncoder().encode(request) else {
            completion(nil, NSError(domain: "Invalid JSON data", code: 0, userInfo: nil))
            return
        }
        
        var urlRequest = URLRequest(url: url)
        urlRequest.httpMethod = "POST"
        urlRequest.httpBody = jsonData
        urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
        
        URLSession.shared.dataTask(with: urlRequest) { data, response, error in
            guard let data = data else {
                completion(nil, error)
                return
            }
            
            do {
                let decodedResponse = try JSONDecoder().decode(JsonRpcResponse<T>.self, from: data)
                if let error = decodedResponse.error {
                    completion(nil, NSError(domain: error.message, code: error.code, userInfo: nil))
                } else {
                    completion(decodedResponse.result, nil)
                }
            } catch let error {
                completion(nil, error)
            }
            
        }.resume()
    }
    
}
1895 chars
65 lines

To use this client, create an instance of JsonRpcClient with the server URL, then call the sendRequest method with the remote method name and parameters. The completion block will return the result as a Swift object or an error if the request fails.

Here's an example usage:

main.swift
let url = URL(string: "https://example.com/jsonrpc")!
let client = JsonRpcClient(url: url)

client.sendRequest(method: "getWeather", params: ["city": "New York"]) { (weather: Weather?, error: Error?) in
    guard let weather = weather else {
        print("Error: \(error)")
        return
    }
    
    print("The temperature in New York is \(weather.temperature) degrees.")
}
379 chars
12 lines

In this example, Weather is a custom struct or class that conforms to the Decodable protocol and maps the JSON response to Swift properties.

gistlibby LogSnag