Skip to main content

json_rpc/
response.rs

1use std::fmt;
2
3use serde::{
4    Deserialize, Deserializer, Serialize, Serializer,
5    de::{self, MapAccess, Visitor},
6};
7use serde_json::value::RawValue;
8
9use crate::{ErrorCode, Id};
10
11/// A JSON-RPC 2.0 error object.
12///
13/// `code` and `message` are required. `data` is optional and MAY contain
14/// additional structured information about the error.
15#[derive(Clone, Debug, Serialize, Deserialize)]
16pub struct Error {
17    /// The error code. Pre-defined codes use the range -32768 to -32000.
18    pub code: i32,
19    /// A short single-sentence description of the error.
20    pub message: String,
21    /// Optional additional error data.
22    #[serde(skip_serializing_if = "Option::is_none")]
23    pub data: Option<Box<RawValue>>,
24}
25
26impl Error {
27    /// Creates a new `Error` with the given code and message.
28    pub fn new(code: i32, message: impl Into<String>) -> Self {
29        Self {
30            code,
31            message: message.into(),
32            data: None,
33        }
34    }
35
36    /// Creates a new `Error` with additional data.
37    pub fn with_data(code: i32, message: impl Into<String>, data: impl Serialize) -> serde_json::Result<Self> {
38        Ok(Self {
39            code,
40            message: message.into(),
41            data: Some(serde_json::value::to_raw_value(&data)?),
42        })
43    }
44
45    /// Creates a parse error response.
46    pub fn parse_error() -> Self {
47        Self::new(ErrorCode::PARSE_ERROR, ErrorCode::default_message(ErrorCode::PARSE_ERROR))
48    }
49
50    /// Creates an invalid request error response.
51    pub fn invalid_request(message: impl Into<String>) -> Self {
52        Self::new(ErrorCode::INVALID_REQUEST, message)
53    }
54
55    /// Creates a method not found error response.
56    pub fn method_not_found(method: impl Into<String>) -> Self {
57        Self::new(ErrorCode::METHOD_NOT_FOUND, format!("Method not found: {}", method.into()))
58    }
59
60    /// Creates an invalid params error response.
61    pub fn invalid_params(message: impl Into<String>) -> Self {
62        Self::new(ErrorCode::INVALID_PARAMS, message)
63    }
64
65    /// Creates an internal error response.
66    pub fn internal_error() -> Self {
67        Self::new(ErrorCode::INTERNAL_ERROR, ErrorCode::default_message(ErrorCode::INTERNAL_ERROR))
68    }
69
70    /// Returns `true` if this error uses a reserved pre-defined code.
71    pub fn is_reserved_code(&self) -> bool {
72        ErrorCode::is_reserved(self.code)
73    }
74}
75
76/// A JSON-RPC 2.0 response.
77///
78/// A response is either a success (containing a `result`) or a failure
79/// (containing an `error`). Per the spec, `result` and `error` MUST NOT
80/// both be present.
81///
82/// The `jsonrpc` field is always serialized as `"2.0"`.
83#[derive(Clone, Debug)]
84pub enum Response {
85    /// A successful response with a result payload.
86    Success {
87        /// The result value from the method invocation.
88        result: Box<RawValue>,
89        /// The request identifier.
90        id: Id,
91    },
92    /// An error response.
93    Error {
94        /// The error details.
95        error: Error,
96        /// The request identifier (null if the id could not be determined).
97        id: Id,
98    },
99}
100
101impl Response {
102    /// Creates a success response.
103    pub fn success(id: Id, result: impl Serialize) -> serde_json::Result<Self> {
104        Ok(Self::Success {
105            result: serde_json::value::to_raw_value(&result)?,
106            id,
107        })
108    }
109
110    /// Creates an error response.
111    pub fn error(id: Id, error: Error) -> Self {
112        Self::Error {
113            error,
114            id,
115        }
116    }
117
118    /// Returns the result if this is a success response.
119    pub fn result(&self) -> Option<&RawValue> {
120        match self {
121            Self::Success {
122                result, ..
123            } => Some(result),
124            Self::Error {
125                ..
126            } => None,
127        }
128    }
129
130    /// Returns the error if this is an error response.
131    pub fn error_ref(&self) -> Option<&Error> {
132        match self {
133            Self::Error {
134                error, ..
135            } => Some(error),
136            Self::Success {
137                ..
138            } => None,
139        }
140    }
141
142    /// Returns the id of the response.
143    pub fn id(&self) -> &Id {
144        match self {
145            Self::Success {
146                id, ..
147            }
148            | Self::Error {
149                id, ..
150            } => id,
151        }
152    }
153
154    /// Returns `true` if this is a success response.
155    pub fn is_success(&self) -> bool {
156        matches!(self, Self::Success { .. })
157    }
158
159    /// Returns `true` if this is an error response.
160    pub fn is_error(&self) -> bool {
161        matches!(self, Self::Error { .. })
162    }
163}
164
165impl Serialize for Response {
166    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
167        use serde::ser::SerializeStruct;
168
169        match self {
170            Self::Success {
171                result,
172                id,
173            } => {
174                let mut s = serializer.serialize_struct("Response", 3)?;
175                s.serialize_field("jsonrpc", "2.0")?;
176                s.serialize_field("result", result)?;
177                s.serialize_field("id", id)?;
178                s.end()
179            }
180            Self::Error {
181                error,
182                id,
183            } => {
184                let mut s = serializer.serialize_struct("Response", 3)?;
185                s.serialize_field("jsonrpc", "2.0")?;
186                s.serialize_field("error", error)?;
187                s.serialize_field("id", id)?;
188                s.end()
189            }
190        }
191    }
192}
193
194impl<'de> Deserialize<'de> for Response {
195    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
196        struct ResponseVisitor;
197
198        impl<'de> Visitor<'de> for ResponseVisitor {
199            type Value = Response;
200
201            fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
202                f.write_str("a JSON-RPC 2.0 response object with jsonrpc, result/error, and optional id")
203            }
204
205            fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
206                let mut result: Option<Box<RawValue>> = None;
207                let mut error: Option<Error> = None;
208                let mut id: Option<Id> = None;
209
210                while let Some(key) = map.next_key::<String>()? {
211                    match key.as_str() {
212                        "jsonrpc" => {
213                            let _version: String = map.next_value()?;
214                        }
215                        "result" => {
216                            if error.is_some() {
217                                return Err(de::Error::custom("response contains both result and error"));
218                            }
219                            let raw: Box<RawValue> = map.next_value()?;
220                            result = Some(raw);
221                        }
222                        "error" => {
223                            if result.is_some() {
224                                return Err(de::Error::custom("response contains both result and error"));
225                            }
226                            error = Some(map.next_value()?);
227                        }
228                        "id" => {
229                            id = Some(map.next_value()?);
230                        }
231                        _ => {
232                            let _: serde::de::IgnoredAny = map.next_value()?;
233                        }
234                    }
235                }
236
237                let id = id.ok_or_else(|| de::Error::missing_field("id"))?;
238
239                match (result, error) {
240                    (Some(result), None) => Ok(Response::Success {
241                        result,
242                        id,
243                    }),
244                    (None, Some(error)) => Ok(Response::Error {
245                        error,
246                        id,
247                    }),
248                    (Some(_), Some(_)) => Err(de::Error::custom("response contains both result and error")),
249                    (None, None) => Err(de::Error::custom("response missing both result and error")),
250                }
251            }
252        }
253
254        deserializer.deserialize_struct("Response", &["jsonrpc", "result", "error", "id"], ResponseVisitor)
255    }
256}
257
258#[cfg(test)]
259mod tests {
260    use serde_json::{Value, json};
261
262    use super::*;
263
264    #[test]
265    fn test_error_object_new() {
266        let err = Error::new(-32000, "Something went wrong");
267        assert_eq!(err.code, -32000);
268        assert_eq!(err.message, "Something went wrong");
269        assert!(err.data.is_none());
270    }
271
272    #[test]
273    fn test_error_object_with_data() {
274        let err = Error::with_data(-32000, "Server error", json!({"detail": "oops"})).unwrap();
275        assert_eq!(err.code, -32000);
276        assert!(err.data.is_some());
277    }
278
279    #[test]
280    fn test_error_object_serialize() {
281        let err = Error::new(-32601, "Method not found");
282        let json = serde_json::to_value(&err).unwrap();
283        assert_eq!(json["code"], json!(-32601));
284        assert_eq!(json["message"], json!("Method not found"));
285        assert!(json.get("data").is_none());
286    }
287
288    #[test]
289    fn test_error_object_serialize_with_data() {
290        let err = Error::with_data(-32000, "Err", json!(42)).unwrap();
291        let json = serde_json::to_value(&err).unwrap();
292        assert_eq!(json["data"], json!(42));
293    }
294
295    #[test]
296    fn test_error_object_deserialize() {
297        let json = json!({"code": -32601, "message": "Method not found"});
298        let err: Error = serde_json::from_value(json).unwrap();
299        assert_eq!(err.code, -32601);
300        assert_eq!(err.message, "Method not found");
301        assert!(err.data.is_none());
302    }
303
304    #[test]
305    fn test_error_object_deserialize_with_data() {
306        let json = json!({"code": -32000, "message": "Err", "data": 42});
307        let err: Error = serde_json::from_value(json).unwrap();
308        assert_eq!(err.code, -32000);
309        assert!(err.data.is_some());
310    }
311
312    #[test]
313    fn test_error_object_parse_error() {
314        let err = Error::parse_error();
315        assert_eq!(err.code, -32700);
316    }
317
318    #[test]
319    fn test_error_object_invalid_request() {
320        let err = Error::invalid_request("missing jsonrpc");
321        assert_eq!(err.code, -32600);
322        assert!(err.message.contains("missing jsonrpc"));
323    }
324
325    #[test]
326    fn test_error_object_method_not_found() {
327        let err = Error::method_not_found("foo");
328        assert_eq!(err.code, -32601);
329        assert!(err.message.contains("foo"));
330    }
331
332    #[test]
333    fn test_error_object_invalid_params() {
334        let err = Error::invalid_params("expected array");
335        assert_eq!(err.code, -32602);
336        assert!(err.message.contains("expected array"));
337    }
338
339    #[test]
340    fn test_error_object_internal_error() {
341        let err = Error::internal_error();
342        assert_eq!(err.code, -32603);
343    }
344
345    #[test]
346    fn test_error_object_is_reserved_code() {
347        assert!(Error::parse_error().is_reserved_code());
348        assert!(!Error::new(1, "app error").is_reserved_code());
349    }
350
351    #[test]
352    fn test_response_success_serialize() {
353        let resp = Response::success(Id::Number(1), json!(42)).unwrap();
354        assert!(resp.is_success());
355        assert!(!resp.is_error());
356        assert_eq!(resp.id(), &Id::Number(1));
357        assert!(resp.result().is_some());
358        assert!(resp.error_ref().is_none());
359
360        let value = serde_json::to_value(&resp).unwrap();
361        assert_eq!(value["jsonrpc"], json!("2.0"));
362        assert_eq!(value["result"], json!(42));
363        assert_eq!(value["id"], json!(1));
364    }
365
366    #[test]
367    fn test_response_error_serialize() {
368        let err = Error::new(-32601, "Method not found");
369        let resp = Response::error(Id::Null, err);
370        assert!(resp.is_error());
371        assert!(!resp.is_success());
372        assert_eq!(resp.id(), &Id::Null);
373        assert!(resp.result().is_none());
374        assert!(resp.error_ref().is_some());
375
376        let value = serde_json::to_value(&resp).unwrap();
377        assert_eq!(value["jsonrpc"], json!("2.0"));
378        assert!(value.get("result").is_none());
379        assert_eq!(value["error"]["code"], json!(-32601));
380        assert_eq!(value["error"]["message"], json!("Method not found"));
381        assert_eq!(value["id"], json!(null));
382    }
383
384    #[test]
385    fn test_response_success_no_extra_fields() {
386        let resp = Response::success(Id::Number(1), "hello").unwrap();
387        let value: Value = serde_json::to_value(&resp).unwrap();
388        assert!(value.get("error").is_none());
389    }
390
391    #[test]
392    fn test_response_error_no_extra_fields() {
393        let err = Error::new(-32600, "Invalid Request");
394        let resp = Response::error(Id::Null, err);
395        let value: Value = serde_json::to_value(&resp).unwrap();
396        assert!(value.get("result").is_none());
397    }
398
399    #[test]
400    fn test_response_deserialize_success() {
401        let json = json!({"jsonrpc": "2.0", "result": 42, "id": 1});
402        let resp: Response = serde_json::from_value(json).unwrap();
403        assert!(resp.is_success());
404        assert_eq!(resp.id(), &Id::Number(1));
405        assert!(resp.result().is_some());
406    }
407
408    #[test]
409    fn test_response_deserialize_error() {
410        let json = json!({"jsonrpc": "2.0", "error": {"code": -32601, "message": "Method not found"}, "id": "1"});
411        let resp: Response = serde_json::from_value(json).unwrap();
412        assert!(resp.is_error());
413        assert_eq!(resp.id(), &Id::String("1".into()));
414        let err = resp.error_ref().unwrap();
415        assert_eq!(err.code, -32601);
416    }
417
418    #[test]
419    fn test_response_deserialize_missing_both_result_and_error() {
420        let json = json!({"jsonrpc": "2.0", "id": 1});
421        let err = serde_json::from_value::<Response>(json).unwrap_err();
422        assert!(err.to_string().contains("missing both result and error"));
423    }
424
425    #[test]
426    fn test_response_deserialize_both_result_and_error() {
427        let json = json!({"jsonrpc": "2.0", "result": 1, "error": {"code": 0, "message": "x"}, "id": 1});
428        let err = serde_json::from_value::<Response>(json).unwrap_err();
429        assert!(err.to_string().contains("both result and error"));
430    }
431
432    #[test]
433    fn test_response_deserialize_missing_id() {
434        let json = json!({"jsonrpc": "2.0", "result": 42});
435        let err = serde_json::from_value::<Response>(json).unwrap_err();
436        assert!(err.to_string().contains("id"));
437    }
438}