| Crates.io | jsoncall |
| lib.rs | jsoncall |
| version | 0.0.3 |
| created_at | 2025-03-08 08:49:34.989332+00 |
| updated_at | 2025-03-27 04:05:05.611575+00 |
| description | A simple asynchronous JSON-RPC 2.0 library leveraging Rust's type system |
| homepage | |
| repository | https://github.com/frozenlib/jsoncall |
| max_upload_size | |
| id | 1584228 |
| size | 146,675 |
A simple asynchronous JSON-RPC 2.0 library leveraging Rust's type system
jsoncall is a simple asynchronous JSON-RPC 2.0 library that maximizes the use of Rust's type system.
It is specifically designed to facilitate the creation of applications where the client launches the server, such as the Language Server Protocol and Model Context Protocol.
tokio and async/awaitserde
typifyanyhow or Box<dyn Error>, with additional functionality to distinguish between information that should be sent externally and information that should nottokio's AsyncBufRead and AsyncWrite traits
Session::from_stdio and Session::from_commandAdd the following to your Cargo.toml:
[dependencies]
jsoncall = "0.0.3"
use serde::{Deserialize, Serialize};
use jsoncall::{Handler, Params, RequestContext, Response, Result, Session, SessionOptions};
#[derive(Debug, Serialize, Deserialize)]
struct HelloRequest {
name: String,
}
#[derive(Debug, Serialize, Deserialize)]
struct HelloResponse {
message: String,
}
struct HelloHandler;
impl Handler for HelloHandler {
fn request(&mut self, method: &str, params: Params, cx: RequestContext) -> Result<Response> {
match method {
"hello" => cx.handle(self.hello(params.to()?)),
_ => cx.method_not_found(),
}
}
}
impl HelloHandler {
fn hello(&self, r: HelloRequest) -> Result<HelloResponse> {
Ok(HelloResponse {
message: format!("Hello, {}!", r.name),
})
}
}
#[tokio::main]
async fn main() -> Result<()> {
// Start server using standard I/O
Ok(Session::from_stdio(HelloHandler, &SessionOptions::default()).wait().await?)
}
use serde::{Deserialize, Serialize};
use tokio::process::Command;
use jsoncall::{Result, Session, SessionOptions};
#[derive(Debug, Serialize, Deserialize)]
struct HelloRequest {
name: String,
}
#[derive(Debug, Serialize, Deserialize)]
struct HelloResponse {
message: String,
}
#[tokio::main]
async fn main() -> Result<()> {
// Launch server process and create session
let client = Session::from_command(
(),
Command::new("cargo").args(["run", "--example", "stdio_server"]),
&SessionOptions::default(),
)?;
// Send request
let response: HelloResponse = client
.request(
"hello",
Some(&HelloRequest {
name: "world".to_string(),
}),
)
.await?;
println!("{:?}", response);
Ok(())
}
use jsoncall::{Handler, Params, RequestContext, Result, Response};
struct ExampleHandler;
impl Handler for ExampleHandler {
fn request(&mut self, method: &str, params: Params, cx: RequestContext) -> Result<Response> {
match method {
"add" => {
let params: (i32, i32) = params.to()?;
cx.handle_async(async move {
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
Ok(params.0 + params.1)
})
}
_ => cx.method_not_found(),
}
}
}
This project is dual licensed under Apache-2.0/MIT. See the two LICENSE-* files for details.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.