1use serde::{Deserialize, Deserializer, Serialize, Serializer};
7use serde_json::Value;
8use std::fmt;
9
10use crate::types::RequestId;
11
12pub const JSONRPC_VERSION: &str = "2.0";
14
15#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct JsonRpcVersion;
18
19impl Serialize for JsonRpcVersion {
20 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
21 where
22 S: Serializer,
23 {
24 serializer.serialize_str(JSONRPC_VERSION)
25 }
26}
27
28impl<'de> Deserialize<'de> for JsonRpcVersion {
29 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
30 where
31 D: Deserializer<'de>,
32 {
33 let version = String::deserialize(deserializer)?;
34 if version == JSONRPC_VERSION {
35 Ok(JsonRpcVersion)
36 } else {
37 Err(serde::de::Error::custom(format!(
38 "Invalid JSON-RPC version: expected '{JSONRPC_VERSION}', got '{version}'"
39 )))
40 }
41 }
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize)]
46pub struct JsonRpcRequest {
47 pub jsonrpc: JsonRpcVersion,
49 pub method: String,
51 #[serde(skip_serializing_if = "Option::is_none", default)]
53 pub params: Option<Value>,
54 pub id: RequestId,
56}
57
58#[derive(Debug, Clone, Serialize)]
67#[serde(untagged)]
68pub enum JsonRpcResponsePayload {
69 Success {
71 result: Value,
73 },
74 Error {
76 error: JsonRpcError,
78 },
79}
80
81impl<'de> Deserialize<'de> for JsonRpcResponsePayload {
82 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
83 where
84 D: serde::Deserializer<'de>,
85 {
86 let mut object = serde_json::Map::<String, Value>::deserialize(deserializer)?;
87 let result_present = object.contains_key("result");
88 let error_present = object.contains_key("error");
89
90 match (result_present, error_present) {
91 (true, false) => Ok(Self::Success {
92 result: object.remove("result").unwrap_or(Value::Null),
93 }),
94 (false, true) => {
95 let error_value = object.remove("error").unwrap_or(Value::Null);
96 let error =
97 JsonRpcError::deserialize(error_value).map_err(serde::de::Error::custom)?;
98 Ok(Self::Error { error })
99 }
100 (true, true) => Err(serde::de::Error::custom(
101 "JSON-RPC response must contain exactly one of `result` or `error`, not both",
102 )),
103 (false, false) => Err(serde::de::Error::custom(
104 "JSON-RPC response must contain exactly one of `result` or `error`",
105 )),
106 }
107 }
108}
109
110#[derive(Debug, Clone, Serialize, Deserialize)]
112pub struct JsonRpcResponse {
113 pub jsonrpc: JsonRpcVersion,
115 #[serde(flatten)]
117 pub payload: JsonRpcResponsePayload,
118 pub id: ResponseId,
120}
121
122#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
124#[serde(transparent)]
125pub struct ResponseId(pub Option<RequestId>);
126
127impl ResponseId {
128 pub fn from_request(id: RequestId) -> Self {
130 Self(Some(id))
131 }
132
133 pub fn null() -> Self {
135 Self(None)
136 }
137
138 pub fn as_request_id(&self) -> Option<&RequestId> {
140 self.0.as_ref()
141 }
142
143 pub fn is_null(&self) -> bool {
145 self.0.is_none()
146 }
147}
148
149#[derive(Debug, Clone, Serialize, Deserialize)]
151pub struct JsonRpcNotification {
152 pub jsonrpc: JsonRpcVersion,
154 pub method: String,
156 #[serde(skip_serializing_if = "Option::is_none", default)]
158 pub params: Option<Value>,
159}
160
161#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
163pub struct JsonRpcError {
164 pub code: i32,
166 pub message: String,
168 #[serde(skip_serializing_if = "Option::is_none", default)]
170 pub data: Option<Value>,
171}
172
173impl JsonRpcError {
174 const SERVER_ERROR_RANGE: std::ops::RangeInclusive<i32> = -32099..=-32000;
179 const STANDARD_CODES: &'static [i32] = &[-32700, -32600, -32601, -32602, -32603];
183
184 pub fn new(code: i32, message: impl Into<String>) -> Self {
191 if !Self::is_valid_code(code) {
192 tracing::warn!(
193 code,
194 "JSON-RPC error code outside reserved server-error range -32099..=-32000 \
195 and not a standardized JSON-RPC 2.0 code; this risks colliding with \
196 future spec assignments"
197 );
198 }
199 Self {
200 code,
201 message: Self::cap_message(message.into()),
202 data: None,
203 }
204 }
205
206 pub fn with_validated_code(
209 code: i32,
210 message: impl Into<String>,
211 ) -> Result<Self, &'static str> {
212 if !Self::is_valid_code(code) {
213 return Err(
214 "JSON-RPC error code must be a standardized code or in the -32099..=-32000 server-error range",
215 );
216 }
217 Ok(Self {
218 code,
219 message: Self::cap_message(message.into()),
220 data: None,
221 })
222 }
223
224 fn is_valid_code(code: i32) -> bool {
225 Self::SERVER_ERROR_RANGE.contains(&code) || Self::STANDARD_CODES.contains(&code)
226 }
227
228 const MESSAGE_BYTE_CAP: usize = 1024;
237
238 fn cap_message(s: String) -> String {
242 if s.len() <= Self::MESSAGE_BYTE_CAP {
243 return s;
244 }
245 let mut end = Self::MESSAGE_BYTE_CAP;
246 while end > 0 && !s.is_char_boundary(end) {
247 end -= 1;
248 }
249 let elided = s.len() - end;
250 let mut out = String::with_capacity(end + 32);
251 out.push_str(&s[..end]);
252 out.push_str(&format!("…[truncated, {elided} bytes elided]"));
253 out
254 }
255
256 fn cap_data_value(data: Value) -> Value {
258 match data {
259 Value::String(s) => Value::String(Self::cap_message(s)),
260 Value::Array(values) => {
261 Value::Array(values.into_iter().map(Self::cap_data_value).collect())
262 }
263 Value::Object(map) => {
264 let capped = map
265 .into_iter()
266 .map(|(k, v)| (k, Self::cap_data_value(v)))
267 .collect();
268 Value::Object(capped)
269 }
270 other => other,
271 }
272 }
273
274 pub fn with_data(code: i32, message: impl Into<String>, data: Value) -> Self {
276 if !Self::is_valid_code(code) {
277 tracing::warn!(
278 code,
279 "JSON-RPC error code outside reserved server-error range -32099..=-32000"
280 );
281 }
282 Self {
283 code,
284 message: Self::cap_message(message.into()),
285 data: Some(Self::cap_data_value(data)),
286 }
287 }
288
289 pub fn parse_error() -> Self {
291 Self::new(-32700, "Parse error")
292 }
293
294 pub fn parse_error_with_details(details: impl Into<String>) -> Self {
296 Self::with_data(
297 -32700,
298 "Parse error",
299 serde_json::json!({ "details": details.into() }),
300 )
301 }
302
303 pub fn invalid_request() -> Self {
305 Self::new(-32600, "Invalid Request")
306 }
307
308 pub fn invalid_request_with_reason(reason: impl Into<String>) -> Self {
310 Self::with_data(
311 -32600,
312 "Invalid Request",
313 serde_json::json!({ "reason": reason.into() }),
314 )
315 }
316
317 pub fn method_not_found(method: &str) -> Self {
319 Self::new(-32601, format!("Method not found: {method}"))
320 }
321
322 pub fn invalid_params(details: &str) -> Self {
324 Self::new(-32602, format!("Invalid params: {details}"))
325 }
326
327 pub fn internal_error(details: &str) -> Self {
329 Self::new(-32603, format!("Internal error: {details}"))
330 }
331
332 pub fn is_parse_error(&self) -> bool {
334 self.code == -32700
335 }
336
337 pub fn is_invalid_request(&self) -> bool {
339 self.code == -32600
340 }
341
342 pub fn is_method_not_found(&self) -> bool {
344 self.code == -32601
345 }
346
347 pub fn is_invalid_params(&self) -> bool {
349 self.code == -32602
350 }
351
352 pub fn is_internal_error(&self) -> bool {
354 self.code == -32603
355 }
356
357 pub fn is_server_error(&self) -> bool {
360 (-32099..=-32000).contains(&self.code)
361 }
362
363 pub fn code(&self) -> i32 {
365 self.code
366 }
367
368 pub fn standard_kind(&self) -> Option<JsonRpcErrorCode> {
371 match self.code {
372 -32700 => Some(JsonRpcErrorCode::ParseError),
373 -32600 => Some(JsonRpcErrorCode::InvalidRequest),
374 -32601 => Some(JsonRpcErrorCode::MethodNotFound),
375 -32602 => Some(JsonRpcErrorCode::InvalidParams),
376 -32603 => Some(JsonRpcErrorCode::InternalError),
377 _ => None,
378 }
379 }
380}
381
382#[derive(Debug, Clone, Copy, PartialEq, Eq)]
384pub enum JsonRpcErrorCode {
385 ParseError,
387 InvalidRequest,
389 MethodNotFound,
391 InvalidParams,
393 InternalError,
395 ApplicationError(i32),
397}
398
399impl JsonRpcErrorCode {
400 pub fn code(&self) -> i32 {
402 match self {
403 Self::ParseError => -32700,
404 Self::InvalidRequest => -32600,
405 Self::MethodNotFound => -32601,
406 Self::InvalidParams => -32602,
407 Self::InternalError => -32603,
408 Self::ApplicationError(code) => *code,
409 }
410 }
411
412 pub fn message(&self) -> &'static str {
414 match self {
415 Self::ParseError => "Parse error",
416 Self::InvalidRequest => "Invalid Request",
417 Self::MethodNotFound => "Method not found",
418 Self::InvalidParams => "Invalid params",
419 Self::InternalError => "Internal error",
420 Self::ApplicationError(_) => "Application error",
421 }
422 }
423}
424
425impl fmt::Display for JsonRpcErrorCode {
426 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
427 write!(f, "{} ({})", self.message(), self.code())
428 }
429}
430
431impl From<JsonRpcErrorCode> for JsonRpcError {
432 fn from(code: JsonRpcErrorCode) -> Self {
433 Self {
434 code: code.code(),
435 message: code.message().to_string(),
436 data: None,
437 }
438 }
439}
440
441impl From<i32> for JsonRpcErrorCode {
442 fn from(code: i32) -> Self {
443 match code {
444 -32700 => Self::ParseError,
445 -32600 => Self::InvalidRequest,
446 -32601 => Self::MethodNotFound,
447 -32602 => Self::InvalidParams,
448 -32603 => Self::InternalError,
449 other => Self::ApplicationError(other),
450 }
451 }
452}
453
454#[derive(Debug, Clone, Serialize, Deserialize)]
458#[serde(untagged)]
459pub enum JsonRpcMessage {
460 Request(JsonRpcRequest),
462 Response(JsonRpcResponse),
464 Notification(JsonRpcNotification),
466}
467
468impl JsonRpcRequest {
469 pub fn new(method: String, params: Option<Value>, id: RequestId) -> Self {
471 Self {
472 jsonrpc: JsonRpcVersion,
473 method,
474 params,
475 id,
476 }
477 }
478
479 pub fn without_params(method: String, id: RequestId) -> Self {
481 Self::new(method, None, id)
482 }
483
484 pub fn with_params<P: Serialize>(
486 method: String,
487 params: P,
488 id: RequestId,
489 ) -> Result<Self, serde_json::Error> {
490 let params_value = serde_json::to_value(params)?;
491 Ok(Self::new(method, Some(params_value), id))
492 }
493}
494
495impl JsonRpcResponse {
496 pub fn success(result: Value, id: RequestId) -> Self {
498 Self {
499 jsonrpc: JsonRpcVersion,
500 payload: JsonRpcResponsePayload::Success { result },
501 id: ResponseId::from_request(id),
502 }
503 }
504
505 pub fn error_response(error: JsonRpcError, id: RequestId) -> Self {
507 Self {
508 jsonrpc: JsonRpcVersion,
509 payload: JsonRpcResponsePayload::Error { error },
510 id: ResponseId::from_request(id),
511 }
512 }
513
514 pub fn parse_error(message: Option<String>) -> Self {
516 let error = JsonRpcError {
517 code: JsonRpcErrorCode::ParseError.code(),
518 message: message.unwrap_or_else(|| JsonRpcErrorCode::ParseError.message().to_string()),
519 data: None,
520 };
521 Self {
522 jsonrpc: JsonRpcVersion,
523 payload: JsonRpcResponsePayload::Error { error },
524 id: ResponseId::null(),
525 }
526 }
527
528 pub fn is_success(&self) -> bool {
530 matches!(self.payload, JsonRpcResponsePayload::Success { .. })
531 }
532
533 pub fn is_error(&self) -> bool {
535 matches!(self.payload, JsonRpcResponsePayload::Error { .. })
536 }
537
538 pub fn result(&self) -> Option<&Value> {
540 match &self.payload {
541 JsonRpcResponsePayload::Success { result } => Some(result),
542 JsonRpcResponsePayload::Error { .. } => None,
543 }
544 }
545
546 pub fn error(&self) -> Option<&JsonRpcError> {
548 match &self.payload {
549 JsonRpcResponsePayload::Success { .. } => None,
550 JsonRpcResponsePayload::Error { error } => Some(error),
551 }
552 }
553
554 pub fn request_id(&self) -> Option<&RequestId> {
556 self.id.as_request_id()
557 }
558
559 pub fn is_parse_error(&self) -> bool {
561 self.id.is_null()
562 }
563
564 pub fn result_mut(&mut self) -> Option<&mut Value> {
566 match &mut self.payload {
567 JsonRpcResponsePayload::Success { result } => Some(result),
568 JsonRpcResponsePayload::Error { .. } => None,
569 }
570 }
571
572 pub fn error_mut(&mut self) -> Option<&mut JsonRpcError> {
574 match &mut self.payload {
575 JsonRpcResponsePayload::Success { .. } => None,
576 JsonRpcResponsePayload::Error { error } => Some(error),
577 }
578 }
579
580 pub fn set_result(&mut self, result: Value) {
582 self.payload = JsonRpcResponsePayload::Success { result };
583 }
584
585 pub fn set_error(&mut self, error: JsonRpcError) {
587 self.payload = JsonRpcResponsePayload::Error { error };
588 }
589}
590
591impl JsonRpcNotification {
592 pub fn new(method: String, params: Option<Value>) -> Self {
594 Self {
595 jsonrpc: JsonRpcVersion,
596 method,
597 params,
598 }
599 }
600
601 pub fn without_params(method: String) -> Self {
603 Self::new(method, None)
604 }
605
606 pub fn with_params<P: Serialize>(method: String, params: P) -> Result<Self, serde_json::Error> {
608 let params_value = serde_json::to_value(params)?;
609 Ok(Self::new(method, Some(params_value)))
610 }
611}
612
613pub mod utils {
615 use super::*;
616
617 #[derive(Debug)]
626 pub enum ParseMessageError {
627 BatchUnsupported,
629 Json(serde_json::Error),
631 }
632
633 impl core::fmt::Display for ParseMessageError {
634 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
635 match self {
636 Self::BatchUnsupported => {
637 f.write_str("JSON-RPC batches are not supported in MCP 2025-11-25")
638 }
639 Self::Json(e) => write!(f, "{e}"),
640 }
641 }
642 }
643
644 impl std::error::Error for ParseMessageError {
645 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
646 match self {
647 Self::BatchUnsupported => None,
648 Self::Json(e) => Some(e),
649 }
650 }
651 }
652
653 impl From<serde_json::Error> for ParseMessageError {
654 fn from(e: serde_json::Error) -> Self {
655 Self::Json(e)
656 }
657 }
658
659 pub fn parse_message(json: &str) -> Result<JsonRpcMessage, serde_json::Error> {
665 serde_json::from_str(json)
666 }
667
668 pub fn parse_message_typed(json: &str) -> Result<JsonRpcMessage, ParseMessageError> {
675 if json.trim_start().as_bytes().first() == Some(&b'[') {
676 return Err(ParseMessageError::BatchUnsupported);
677 }
678 Ok(serde_json::from_str(json)?)
679 }
680
681 pub fn serialize_message(message: &JsonRpcMessage) -> Result<String, serde_json::Error> {
683 serde_json::to_string(message)
684 }
685
686 pub fn extract_method(json: &str) -> Option<String> {
688 if let Ok(value) = serde_json::from_str::<serde_json::Value>(json)
690 && let Some(method) = value.get("method")
691 {
692 return method.as_str().map(String::from);
693 }
694 None
695 }
696}
697
698pub mod http {
720 use serde::{Deserialize, Serialize};
721 use serde_json::Value;
722
723 #[derive(Debug, Clone, Serialize, Deserialize)]
728 pub struct HttpJsonRpcRequest {
729 pub jsonrpc: String,
731 #[serde(default)]
733 pub id: Option<Value>,
734 pub method: String,
736 #[serde(default)]
738 pub params: Option<Value>,
739 }
740
741 impl HttpJsonRpcRequest {
742 pub fn is_valid(&self) -> bool {
744 self.jsonrpc == "2.0" && !self.method.is_empty()
745 }
746
747 pub fn is_notification(&self) -> bool {
749 self.id.is_none()
750 }
751
752 pub fn id_string(&self) -> Option<String> {
754 self.id.as_ref().map(|v| match v {
755 Value::String(s) => s.clone(),
756 Value::Number(n) => n.to_string(),
757 _ => v.to_string(),
758 })
759 }
760 }
761
762 #[derive(Debug, Clone, Serialize, Deserialize)]
767 pub struct HttpJsonRpcResponse {
768 pub jsonrpc: String,
770 #[serde(default)]
772 pub id: Option<Value>,
773 #[serde(skip_serializing_if = "Option::is_none")]
775 pub result: Option<Value>,
776 #[serde(skip_serializing_if = "Option::is_none")]
778 pub error: Option<super::JsonRpcError>,
779 }
780
781 impl HttpJsonRpcResponse {
782 pub fn success(id: Option<Value>, result: Value) -> Self {
784 Self {
785 jsonrpc: "2.0".to_string(),
786 id,
787 result: Some(result),
788 error: None,
789 }
790 }
791
792 pub fn error(id: Option<Value>, error: super::JsonRpcError) -> Self {
794 Self {
795 jsonrpc: "2.0".to_string(),
796 id,
797 result: None,
798 error: Some(error),
799 }
800 }
801
802 pub fn error_from_code(id: Option<Value>, code: i32, message: impl Into<String>) -> Self {
804 Self::error(id, super::JsonRpcError::new(code, message))
805 }
806
807 pub fn invalid_request(id: Option<Value>, reason: impl Into<String>) -> Self {
809 Self::error(id, super::JsonRpcError::invalid_request_with_reason(reason))
810 }
811
812 pub fn parse_error(details: Option<String>) -> Self {
814 Self::error(
815 None,
816 details
817 .map(super::JsonRpcError::parse_error_with_details)
818 .unwrap_or_else(super::JsonRpcError::parse_error),
819 )
820 }
821
822 pub fn internal_error(id: Option<Value>, details: &str) -> Self {
824 Self::error(id, super::JsonRpcError::internal_error(details))
825 }
826
827 pub fn method_not_found(id: Option<Value>, method: &str) -> Self {
829 Self::error(id, super::JsonRpcError::method_not_found(method))
830 }
831
832 pub fn is_error(&self) -> bool {
834 self.error.is_some()
835 }
836
837 pub fn is_success(&self) -> bool {
839 self.result.is_some() && self.error.is_none()
840 }
841 }
842
843 #[cfg(test)]
844 mod tests {
845 use super::*;
846
847 #[test]
848 fn test_http_request_parsing() {
849 let json = r#"{"jsonrpc":"2.0","method":"test","id":1,"params":{"key":"value"}}"#;
850 let request: HttpJsonRpcRequest = serde_json::from_str(json).unwrap();
851 assert!(request.is_valid());
852 assert!(!request.is_notification());
853 assert_eq!(request.method, "test");
854 }
855
856 #[test]
857 fn test_http_request_invalid_version() {
858 let json = r#"{"jsonrpc":"1.0","method":"test","id":1}"#;
859 let request: HttpJsonRpcRequest = serde_json::from_str(json).unwrap();
860 assert!(!request.is_valid());
861 }
862
863 #[test]
864 fn test_http_response_success() {
865 let response = HttpJsonRpcResponse::success(
866 Some(Value::Number(1.into())),
867 serde_json::json!({"result": "ok"}),
868 );
869 assert!(response.is_success());
870 assert!(!response.is_error());
871 }
872
873 #[test]
874 fn test_http_response_error() {
875 let response = HttpJsonRpcResponse::invalid_request(
876 Some(Value::String("req-1".into())),
877 "jsonrpc must be 2.0",
878 );
879 assert!(!response.is_success());
880 assert!(response.is_error());
881 }
882
883 #[test]
884 fn test_http_response_serialization() {
885 let response = HttpJsonRpcResponse::success(
886 Some(Value::Number(1.into())),
887 serde_json::json!({"data": "test"}),
888 );
889 let json = serde_json::to_string(&response).unwrap();
890 assert!(json.contains(r#""jsonrpc":"2.0""#));
891 assert!(json.contains(r#""result""#));
892 assert!(!json.contains(r#""error""#));
893 }
894 }
895}
896
897#[cfg(test)]
902#[path = "jsonrpc/tests.rs"]
903mod extended_tests;
904
905#[cfg(test)]
906mod tests {
907 use super::*;
908 use serde_json::json;
909
910 #[test]
911 fn test_jsonrpc_version() {
912 let version = JsonRpcVersion;
913 let json = serde_json::to_string(&version).unwrap();
914 assert_eq!(json, "\"2.0\"");
915
916 let parsed: JsonRpcVersion = serde_json::from_str(&json).unwrap();
917 assert_eq!(parsed, version);
918 }
919
920 #[test]
921 fn test_request_creation() {
922 let request = JsonRpcRequest::new(
923 "test_method".to_string(),
924 Some(json!({"key": "value"})),
925 RequestId::String("test-id".to_string()),
926 );
927
928 assert_eq!(request.method, "test_method");
929 assert!(request.params.is_some());
930 }
931
932 #[test]
933 fn test_response_creation() {
934 let response = JsonRpcResponse::success(
935 json!({"result": "success"}),
936 RequestId::String("test-id".to_string()),
937 );
938
939 assert!(response.is_success());
940 assert!(!response.is_error());
941 assert!(response.result().is_some());
942 assert!(response.error().is_none());
943 assert!(!response.is_parse_error());
944 }
945
946 #[test]
947 fn test_error_response() {
948 let error = JsonRpcError::from(JsonRpcErrorCode::MethodNotFound);
949 let response =
950 JsonRpcResponse::error_response(error, RequestId::String("test-id".to_string()));
951
952 assert!(!response.is_success());
953 assert!(response.is_error());
954 assert!(response.result().is_none());
955 assert!(response.error().is_some());
956 assert!(!response.is_parse_error());
957 }
958
959 #[test]
960 fn test_response_payload_accepts_null_result() {
961 let raw = r#"{"jsonrpc":"2.0","id":1,"result":null}"#;
962 let response: JsonRpcResponse = serde_json::from_str(raw).unwrap();
963 assert!(response.is_success());
964 assert_eq!(response.result(), Some(&Value::Null));
965 }
966
967 #[test]
968 fn test_parse_error_response() {
969 let response = JsonRpcResponse::parse_error(Some("Invalid JSON".to_string()));
970
971 assert!(!response.is_success());
972 assert!(response.is_error());
973 assert!(response.result().is_none());
974 assert!(response.error().is_some());
975 assert!(response.is_parse_error());
976 assert!(response.request_id().is_none());
977
978 let error = response.error().unwrap();
980 assert_eq!(error.code, JsonRpcErrorCode::ParseError.code());
981 assert_eq!(error.message, "Invalid JSON");
982 }
983
984 #[test]
985 fn test_notification() {
986 let notification = JsonRpcNotification::without_params("test_notification".to_string());
987 assert_eq!(notification.method, "test_notification");
988 assert!(notification.params.is_none());
989 }
990
991 #[test]
992 fn test_serialization() {
993 let request = JsonRpcRequest::new(
994 "test_method".to_string(),
995 Some(json!({"param": "value"})),
996 RequestId::String("123".to_string()),
997 );
998
999 let json = serde_json::to_string(&request).unwrap();
1000 let parsed: JsonRpcRequest = serde_json::from_str(&json).unwrap();
1001
1002 assert_eq!(parsed.method, request.method);
1003 assert_eq!(parsed.params, request.params);
1004 }
1005
1006 #[test]
1007 fn test_utils() {
1008 let json = r#"{"jsonrpc":"2.0","method":"test","id":"123"}"#;
1009 assert_eq!(utils::extract_method(json), Some("test".to_string()));
1010 }
1011
1012 #[test]
1013 fn test_error_codes() {
1014 let parse_error = JsonRpcErrorCode::ParseError;
1015 assert_eq!(parse_error.code(), -32700);
1016 assert_eq!(parse_error.message(), "Parse error");
1017
1018 let app_error = JsonRpcErrorCode::ApplicationError(-32001);
1019 assert_eq!(app_error.code(), -32001);
1020 }
1021}