1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct JsonRpcRequest {
6 pub jsonrpc: String,
7 pub method: String,
8 pub params: Option<Value>,
9 pub id: Option<Value>,
10}
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct JsonRpcResponse {
14 pub jsonrpc: String,
15 pub result: Option<Value>,
16 pub error: Option<JsonRpcError>,
17 pub id: Option<Value>,
18}
19
20#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct JsonRpcError {
22 pub code: i64,
23 pub message: String,
24 pub data: Option<Value>,
25}
26
27impl JsonRpcRequest {}
28
29impl JsonRpcResponse {
30 pub fn success(id: Option<Value>, result: Value) -> Self {
31 Self {
32 jsonrpc: "2.0".to_string(),
33 result: Some(result),
34 error: None,
35 id,
36 }
37 }
38
39 pub fn error(id: Option<Value>, code: i64, message: String) -> Self {
40 Self {
41 jsonrpc: "2.0".to_string(),
42 result: None,
43 error: Some(JsonRpcError {
44 code,
45 message,
46 data: None,
47 }),
48 id,
49 }
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56 use serde_json::json;
57
58 #[test]
59 fn test_request_serialize_deserialize() {
60 let req = JsonRpcRequest {
61 jsonrpc: "2.0".to_string(),
62 method: "test_method".to_string(),
63 params: Some(json!({"key": "value"})),
64 id: Some(Value::Number(1.into())),
65 };
66 let json = serde_json::to_string(&req).unwrap();
67 let deserialized: JsonRpcRequest = serde_json::from_str(&json).unwrap();
68 assert_eq!(deserialized.jsonrpc, "2.0");
69 assert_eq!(deserialized.method, "test_method");
70 assert_eq!(deserialized.params, Some(json!({"key": "value"})));
71 assert_eq!(deserialized.id, Some(Value::Number(1.into())));
72 }
73
74 #[test]
75 fn test_request_without_params() {
76 let req = JsonRpcRequest {
77 jsonrpc: "2.0".to_string(),
78 method: "initialize".to_string(),
79 params: None,
80 id: Some(Value::Number(1.into())),
81 };
82 let json = serde_json::to_string(&req).unwrap();
83 let deserialized: JsonRpcRequest = serde_json::from_str(&json).unwrap();
84 assert!(deserialized.params.is_none());
85 }
86
87 #[test]
88 fn test_request_with_string_id() {
89 let req = JsonRpcRequest {
90 jsonrpc: "2.0".to_string(),
91 method: "tools/list".to_string(),
92 params: None,
93 id: Some(Value::String("req-1".into())),
94 };
95 let json = serde_json::to_string(&req).unwrap();
96 let deserialized: JsonRpcRequest = serde_json::from_str(&json).unwrap();
97 assert_eq!(deserialized.id, Some(Value::String("req-1".into())));
98 }
99
100 #[test]
101 fn test_response_success() {
102 let resp = JsonRpcResponse::success(Some(Value::Number(1.into())), json!({"result": "ok"}));
103 assert_eq!(resp.jsonrpc, "2.0");
104 assert_eq!(resp.result, Some(json!({"result": "ok"})));
105 assert!(resp.error.is_none());
106 assert_eq!(resp.id, Some(Value::Number(1.into())));
107 }
108
109 #[test]
110 fn test_response_success_null_id() {
111 let resp = JsonRpcResponse::success(None, json!("ok"));
112 assert!(resp.id.is_none());
113 }
114
115 #[test]
116 fn test_response_error() {
117 let resp = JsonRpcResponse::error(Some(Value::Number(1.into())), -32700, "Parse error".into());
118 assert_eq!(resp.jsonrpc, "2.0");
119 assert!(resp.result.is_none());
120 let err = resp.error.unwrap();
121 assert_eq!(err.code, -32700);
122 assert_eq!(err.message, "Parse error");
123 assert!(err.data.is_none());
124 }
125
126 #[test]
127 fn test_response_error_with_null_id() {
128 let resp = JsonRpcResponse::error(None, -32601, "Not found".into());
129 assert!(resp.id.is_none());
130 }
131
132 #[test]
133 fn test_response_serde_roundtrip() {
134 let resp = JsonRpcResponse::success(Some(Value::Number(42.into())), json!([1, 2, 3]));
135 let json = serde_json::to_string(&resp).unwrap();
136 let deserialized: JsonRpcResponse = serde_json::from_str(&json).unwrap();
137 assert_eq!(deserialized.jsonrpc, "2.0");
138 assert_eq!(deserialized.result, Some(json!([1, 2, 3])));
139 assert_eq!(deserialized.id, Some(Value::Number(42.into())));
140 }
141
142 #[test]
143 fn test_error_serde_roundtrip() {
144 let resp = JsonRpcResponse::error(Some(json!("abc")), -32000, "DB error".into());
145 let json = serde_json::to_string(&resp).unwrap();
146 let deserialized: JsonRpcResponse = serde_json::from_str(&json).unwrap();
147 let err = deserialized.error.unwrap();
148 assert_eq!(err.code, -32000);
149 assert_eq!(err.message, "DB error");
150 }
151
152 #[test]
153 fn test_minimal_request() {
154 let json = r#"{"jsonrpc":"2.0","method":"ping","id":1}"#;
155 let req: JsonRpcRequest = serde_json::from_str(json).unwrap();
156 assert_eq!(req.jsonrpc, "2.0");
157 assert_eq!(req.method, "ping");
158 assert!(req.params.is_none());
159 }
160
161 #[test]
162 fn test_request_with_null_params() {
163 let json = r#"{"jsonrpc":"2.0","method":"ping","params":null,"id":1}"#;
164 let req: JsonRpcRequest = serde_json::from_str(json).unwrap();
165 assert!(req.params.is_none());
166 }
167
168 #[test]
169 fn test_request_with_num_id_zero() {
170 let json = r#"{"jsonrpc":"2.0","method":"initialize","id":0}"#;
171 let req: JsonRpcRequest = serde_json::from_str(json).unwrap();
172 assert_eq!(req.id, Some(Value::Number(0.into())));
173 }
174
175 #[test]
176 fn test_response_with_error_data() {
177 let resp = JsonRpcResponse {
178 jsonrpc: "2.0".to_string(),
179 result: None,
180 error: Some(JsonRpcError {
181 code: -32000,
182 message: "custom error".into(),
183 data: Some(json!({"detail": "something broke"})),
184 }),
185 id: Some(Value::Number(1.into())),
186 };
187 let json = serde_json::to_string(&resp).unwrap();
188 let deserialized: JsonRpcResponse = serde_json::from_str(&json).unwrap();
189 let err = deserialized.error.unwrap();
190 assert_eq!(err.data, Some(json!({"detail": "something broke"})));
191 }
192}
193