From 87999cf7e7cf8763550d867e64511b2e2736d01d Mon Sep 17 00:00:00 2001 From: ArtificialPB Date: Thu, 4 Jul 2024 21:08:07 +0200 Subject: [PATCH] feat(types): serialize `id` in `Response` before `result`/`error` fields (#1421) --- core/src/server/helpers.rs | 2 +- core/src/server/method_response.rs | 8 +++---- server/src/tests/http.rs | 14 ++++++------ server/src/tests/ws.rs | 18 ++++++++-------- test-utils/src/helpers.rs | 34 +++++++++++++++--------------- tests/tests/proc_macros.rs | 6 +++--- tests/tests/rpc_module.rs | 8 +++---- types/src/response.rs | 9 ++++---- 8 files changed, 50 insertions(+), 49 deletions(-) diff --git a/core/src/server/helpers.rs b/core/src/server/helpers.rs index f47c8c8f38..0fcdd932cb 100644 --- a/core/src/server/helpers.rs +++ b/core/src/server/helpers.rs @@ -184,7 +184,7 @@ mod tests { let rp = &Response::new(result, Id::Number(1)); assert!(serde_json::to_writer(&mut writer, rp).is_ok()); - assert_eq!(String::from_utf8(writer.into_bytes()).unwrap(), r#"{"jsonrpc":"2.0","result":"success","id":1}"#); + assert_eq!(String::from_utf8(writer.into_bytes()).unwrap(), r#"{"jsonrpc":"2.0","id":1,"result":"success"}"#); } #[test] diff --git a/core/src/server/method_response.rs b/core/src/server/method_response.rs index f9e134504c..5981efa721 100644 --- a/core/src/server/method_response.rs +++ b/core/src/server/method_response.rs @@ -476,7 +476,7 @@ mod tests { builder.append(&method).unwrap(); let batch = builder.finish(); - assert_eq!(batch.0, r#"[{"jsonrpc":"2.0","result":"a","id":1}]"#) + assert_eq!(batch.0, r#"[{"jsonrpc":"2.0","id":1,"result":"a"}]"#) } #[test] @@ -492,14 +492,14 @@ mod tests { builder.append(&m1).unwrap(); let batch = builder.finish(); - assert_eq!(batch.0, r#"[{"jsonrpc":"2.0","result":"a","id":1},{"jsonrpc":"2.0","result":"a","id":1}]"#) + assert_eq!(batch.0, r#"[{"jsonrpc":"2.0","id":1,"result":"a"},{"jsonrpc":"2.0","id":1,"result":"a"}]"#) } #[test] fn batch_empty_err() { let batch = BatchResponseBuilder::new_with_limit(1024).finish(); - let exp_err = r#"{"jsonrpc":"2.0","error":{"code":-32600,"message":"Invalid request"},"id":null}"#; + let exp_err = r#"{"jsonrpc":"2.0","id":null,"error":{"code":-32600,"message":"Invalid request"}}"#; assert_eq!(batch.0, exp_err); } @@ -510,7 +510,7 @@ mod tests { let batch = BatchResponseBuilder::new_with_limit(63).append(&method).unwrap_err(); - let exp_err = r#"{"jsonrpc":"2.0","error":{"code":-32011,"message":"The batch response was too large","data":"Exceeded max limit of 63"},"id":null}"#; + let exp_err = r#"{"jsonrpc":"2.0","id":null,"error":{"code":-32011,"message":"The batch response was too large","data":"Exceeded max limit of 63"}}"#; assert_eq!(batch.result, exp_err); } } diff --git a/server/src/tests/http.rs b/server/src/tests/http.rs index 3942304683..1897def96b 100644 --- a/server/src/tests/http.rs +++ b/server/src/tests/http.rs @@ -154,7 +154,7 @@ async fn single_method_call_with_multiple_params_of_different_types() { async fn single_method_call_with_faulty_params_returns_err() { let (addr, _handle) = server().with_default_timeout().await.unwrap(); let uri = to_http_uri(addr); - let expected = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid params","data":"invalid type: string \"this should be a number\", expected u64 at line 1 column 26"},"id":1}"#; + let expected = r#"{"jsonrpc":"2.0","id":1,"error":{"code":-32602,"message":"Invalid params","data":"invalid type: string \"this should be a number\", expected u64 at line 1 column 26"}}"#; let req = r#"{"jsonrpc":"2.0","method":"add", "params":["this should be a number"],"id":1}"#; let response = http_request(req.into(), uri).with_default_timeout().await.unwrap().unwrap(); @@ -212,7 +212,7 @@ async fn valid_batched_method_calls() { assert_eq!(response.status, StatusCode::OK); assert_eq!( response.body, - r#"[{"jsonrpc":"2.0","result":3,"id":1},{"jsonrpc":"2.0","result":7,"id":2},{"jsonrpc":"2.0","result":"lo","id":3},{"jsonrpc":"2.0","result":11,"id":4}]"# + r#"[{"jsonrpc":"2.0","id":1,"result":3},{"jsonrpc":"2.0","id":2,"result":7},{"jsonrpc":"2.0","id":3,"result":"lo"},{"jsonrpc":"2.0","id":4,"result":11}]"# ); } @@ -278,7 +278,7 @@ async fn batch_with_mixed_calls() { {"foo": "boo"}, {"jsonrpc": "2.0", "method": "foo.get", "params": {"name": "myself"}, "id": "5"} ]"#; - let res = r#"[{"jsonrpc":"2.0","result":7,"id":"1"},{"jsonrpc":"2.0","error":{"code":-32600,"message":"Invalid request"},"id":null},{"jsonrpc":"2.0","error":{"code":-32601,"message":"Method not found"},"id":"5"}]"#; + let res = r#"[{"jsonrpc":"2.0","id":"1","result":7},{"jsonrpc":"2.0","id":null,"error":{"code":-32600,"message":"Invalid request"}},{"jsonrpc":"2.0","id":"5","error":{"code":-32601,"message":"Method not found"}}]"#; let response = http_request(req.into(), uri.clone()).with_default_timeout().await.unwrap().unwrap(); assert_eq!(response.status, StatusCode::OK); assert_eq!(response.body, res); @@ -295,7 +295,7 @@ async fn batch_notif_without_params_works() { {"jsonrpc": "2.0", "method": "add", "params": [1,2,4], "id": "1"}, {"jsonrpc": "2.0", "method": "add"} ]"#; - let res = r#"[{"jsonrpc":"2.0","result":7,"id":"1"}]"#; + let res = r#"[{"jsonrpc":"2.0","id":"1","result":7}]"#; let response = http_request(req.into(), uri.clone()).with_default_timeout().await.unwrap().unwrap(); assert_eq!(response.status, StatusCode::OK); assert_eq!(response.body, res); @@ -346,20 +346,20 @@ async fn whitespace_is_not_significant() { let req = r#" {"jsonrpc":"2.0","method":"add", "params":[1, 2],"id":1}"#; let response = http_request(req.into(), uri.clone()).await.unwrap(); - let expected = r#"{"jsonrpc":"2.0","result":3,"id":1}"#; + let expected = r#"{"jsonrpc":"2.0","id":1,"result":3}"#; assert_eq!(response.status, StatusCode::OK); assert_eq!(response.body, expected); let req = r#" [{"jsonrpc":"2.0","method":"add", "params":[1, 2],"id":1}]"#; let response = http_request(req.into(), uri.clone()).await.unwrap(); - let expected = r#"[{"jsonrpc":"2.0","result":3,"id":1}]"#; + let expected = r#"[{"jsonrpc":"2.0","id":1,"result":3}]"#; assert_eq!(response.status, StatusCode::OK); assert_eq!(response.body, expected); // Up to 127 whitespace chars are accepted. let req = format!("{}{}", " ".repeat(127), r#"{"jsonrpc":"2.0","method":"add", "params":[1, 2],"id":1}"#); let response = http_request(req.into(), uri.clone()).await.unwrap(); - let expected = r#"{"jsonrpc":"2.0","result":3,"id":1}"#; + let expected = r#"{"jsonrpc":"2.0","id":1,"result":3}"#; assert_eq!(response.status, StatusCode::OK); assert_eq!(response.body, expected); diff --git a/server/src/tests/ws.rs b/server/src/tests/ws.rs index c16c88961f..6a6b1ecf2a 100644 --- a/server/src/tests/ws.rs +++ b/server/src/tests/ws.rs @@ -203,7 +203,7 @@ async fn batch_method_call_works() { let response = client.send_request_text(batch).with_default_timeout().await.unwrap().unwrap(); assert_eq!( response, - r#"[{"jsonrpc":"2.0","result":"Yawn!","id":123},{"jsonrpc":"2.0","result":"hello","id":1},{"jsonrpc":"2.0","result":"hello","id":2},{"jsonrpc":"2.0","result":"hello","id":3}]"# + r#"[{"jsonrpc":"2.0","id":123,"result":"Yawn!"},{"jsonrpc":"2.0","id":1,"result":"hello"},{"jsonrpc":"2.0","id":2,"result":"hello"},{"jsonrpc":"2.0","id":3,"result":"hello"}]"# ); } @@ -223,7 +223,7 @@ async fn batch_method_call_where_some_calls_fail() { assert_eq!( response, - r#"[{"jsonrpc":"2.0","result":"hello","id":1},{"jsonrpc":"2.0","error":{"code":-32000,"message":"MyAppError"},"id":2},{"jsonrpc":"2.0","result":79,"id":3}]"# + r#"[{"jsonrpc":"2.0","id":1,"result":"hello"},{"jsonrpc":"2.0","id":2,"error":{"code":-32000,"message":"MyAppError"}},{"jsonrpc":"2.0","id":3,"result":79}]"# ); } @@ -278,7 +278,7 @@ async fn whitespace_is_not_significant() { let req = r#" [{"jsonrpc":"2.0","method":"add", "params":[1, 2],"id":1}]"#; let response = client.send_request_text(req).await.unwrap(); - assert_eq!(response, r#"[{"jsonrpc":"2.0","result":3,"id":1}]"#); + assert_eq!(response, r#"[{"jsonrpc":"2.0","id":1,"result":3}]"#); // Up to 127 whitespace chars are accepted. let req = format!("{}{}", " ".repeat(127), r#"{"jsonrpc":"2.0","method":"add", "params":[1, 2],"id":1}"#); @@ -305,7 +305,7 @@ async fn single_method_call_with_params_works() { async fn single_method_call_with_faulty_params_returns_err() { let addr = server().await; let mut client = WebSocketTestClient::new(addr).with_default_timeout().await.unwrap().unwrap(); - let expected = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid params","data":"invalid type: string \"should be a number\", expected u64 at line 1 column 21"},"id":1}"#; + let expected = r#"{"jsonrpc":"2.0","id":1,"error":{"code":-32602,"message":"Invalid params","data":"invalid type: string \"should be a number\", expected u64 at line 1 column 21"}}"#; let req = r#"{"jsonrpc":"2.0","method":"add", "params":["should be a number"],"id":1}"#; let response = client.send_request_text(req).with_default_timeout().await.unwrap().unwrap(); @@ -486,7 +486,7 @@ async fn valid_request_that_fails_to_execute_should_not_close_connection() { // Good request, but causes error. let req = r#"{"jsonrpc":"2.0","method":"call_fail","params":[],"id":123}"#; let response = client.send_request_text(req).with_default_timeout().await.unwrap().unwrap(); - assert_eq!(response, r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"MyAppError"},"id":123}"#); + assert_eq!(response, r#"{"jsonrpc":"2.0","id":123,"error":{"code":-32000,"message":"MyAppError"}}"#); // Connection is still good. let request = r#"{"jsonrpc":"2.0","method":"say_hello","id":333}"#; @@ -585,9 +585,9 @@ async fn custom_subscription_id_works() { let mut client = WebSocketTestClient::new(addr).with_default_timeout().await.unwrap().unwrap(); let sub = client.send_request_text(call("subscribe_hello", Vec::<()>::new(), Id::Num(0))).await.unwrap(); - assert_eq!(&sub, r#"{"jsonrpc":"2.0","result":"0xdeadbeef","id":0}"#); + assert_eq!(&sub, r#"{"jsonrpc":"2.0","id":0,"result":"0xdeadbeef"}"#); let unsub = client.send_request_text(call("unsubscribe_hello", vec!["0xdeadbeef"], Id::Num(1))).await.unwrap(); - assert_eq!(&unsub, r#"{"jsonrpc":"2.0","result":true,"id":1}"#); + assert_eq!(&unsub, r#"{"jsonrpc":"2.0","id":1,"result":true}"#); } #[tokio::test] @@ -694,7 +694,7 @@ async fn batch_with_mixed_calls() { {"foo": "boo"}, {"jsonrpc": "2.0", "method": "foo.get", "params": {"name": "myself"}, "id": "5"} ]"#; - let res = r#"[{"jsonrpc":"2.0","result":7,"id":"1"},{"jsonrpc":"2.0","error":{"code":-32600,"message":"Invalid request"},"id":null},{"jsonrpc":"2.0","error":{"code":-32601,"message":"Method not found"},"id":"5"}]"#; + let res = r#"[{"jsonrpc":"2.0","id":"1","result":7},{"jsonrpc":"2.0","id":null,"error":{"code":-32600,"message":"Invalid request"}},{"jsonrpc":"2.0","id":"5","error":{"code":-32601,"message":"Method not found"}}]"#; let response = client.send_request_text(req.to_string()).with_default_timeout().await.unwrap().unwrap(); assert_eq!(response, res); } @@ -710,7 +710,7 @@ async fn batch_notif_without_params_works() { {"jsonrpc": "2.0", "method": "add", "params": [1,2,4], "id": "1"}, {"jsonrpc": "2.0", "method": "add"} ]"#; - let res = r#"[{"jsonrpc":"2.0","result":7,"id":"1"}]"#; + let res = r#"[{"jsonrpc":"2.0","id":"1","result":7}]"#; let response = client.send_request_text(req.to_string()).with_default_timeout().await.unwrap().unwrap(); assert_eq!(response, res); } diff --git a/test-utils/src/helpers.rs b/test-utils/src/helpers.rs index 275c23c883..d8831af401 100644 --- a/test-utils/src/helpers.rs +++ b/test-utils/src/helpers.rs @@ -60,56 +60,56 @@ pub fn to_http_uri(sockaddr: SocketAddr) -> Uri { } pub fn ok_response(result: Value, id: Id) -> String { - format!(r#"{{"jsonrpc":"2.0","result":{},"id":{}}}"#, result, serde_json::to_string(&id).unwrap()) + format!(r#"{{"jsonrpc":"2.0","id":{},"result":{}}}"#, serde_json::to_string(&id).unwrap(), result) } pub fn method_not_found(id: Id) -> String { format!( - r#"{{"jsonrpc":"2.0","error":{{"code":-32601,"message":"Method not found"}},"id":{}}}"#, + r#"{{"jsonrpc":"2.0","id":{},"error":{{"code":-32601,"message":"Method not found"}}}}"#, serde_json::to_string(&id).unwrap() ) } pub fn parse_error(id: Id) -> String { format!( - r#"{{"jsonrpc":"2.0","error":{{"code":-32700,"message":"Parse error"}},"id":{}}}"#, + r#"{{"jsonrpc":"2.0","id":{},"error":{{"code":-32700,"message":"Parse error"}}}}"#, serde_json::to_string(&id).unwrap() ) } pub fn oversized_request(max_limit: u32) -> String { format!( - r#"{{"jsonrpc":"2.0","error":{{"code":-32007,"message":"Request is too big","data":"Exceeded max limit of {max_limit}"}},"id":null}}"# + r#"{{"jsonrpc":"2.0","id":null,"error":{{"code":-32007,"message":"Request is too big","data":"Exceeded max limit of {max_limit}"}}}}"# ) } pub fn batches_not_supported() -> String { - r#"{"jsonrpc":"2.0","error":{"code":-32005,"message":"Batched requests are not supported by this server"},"id":null}"#.into() + r#"{"jsonrpc":"2.0","id":null,"error":{"code":-32005,"message":"Batched requests are not supported by this server"}}"#.into() } pub fn batches_too_large(max_limit: usize) -> String { format!( - r#"{{"jsonrpc":"2.0","error":{{"code":-32010,"message":"The batch request was too large","data":"Exceeded max limit of {max_limit}"}},"id":null}}"# + r#"{{"jsonrpc":"2.0","id":null,"error":{{"code":-32010,"message":"The batch request was too large","data":"Exceeded max limit of {max_limit}"}}}}"# ) } pub fn batch_response_too_large(max_limit: usize) -> String { format!( - r#"{{"jsonrpc":"2.0","error":{{"code":-32011,"message":"The batch response was too large","data":"Exceeded max limit of {max_limit}"}},"id":null}}"# + r#"{{"jsonrpc":"2.0","id":null,"error":{{"code":-32011,"message":"The batch response was too large","data":"Exceeded max limit of {max_limit}"}}}}"# ) } pub fn oversized_response(id: Id, max_limit: u32) -> String { format!( - r#"{{"jsonrpc":"2.0","error":{{"code":-32008,"message":"Response is too big","data":"Exceeded max limit of {}"}},"id":{}}}"#, - max_limit, + r#"{{"jsonrpc":"2.0","id":{},"error":{{"code":-32008,"message":"Response is too big","data":"Exceeded max limit of {}"}}}}"#, serde_json::to_string(&id).unwrap(), + max_limit, ) } pub fn invalid_request(id: Id) -> String { format!( - r#"{{"jsonrpc":"2.0","error":{{"code":-32600,"message":"Invalid request"}},"id":{}}}"#, + r#"{{"jsonrpc":"2.0","id":{},"error":{{"code":-32600,"message":"Invalid request"}}}}"#, serde_json::to_string(&id).unwrap() ) } @@ -121,7 +121,7 @@ pub fn invalid_batch(ids: Vec) -> String { for (i, id) in ids.iter().enumerate() { write!( result, - r#"{{"jsonrpc":"2.0","error":{{"code":-32600,"message":"Invalid request"}},"id":{}}}{}"#, + r#"{{"jsonrpc":"2.0","id":{},"error":{{"code":-32600,"message":"Invalid request"}}}}{}"#, serde_json::to_string(&id).unwrap(), if i + 1 == ids.len() { "" } else { "," } ) @@ -133,7 +133,7 @@ pub fn invalid_batch(ids: Vec) -> String { pub fn invalid_params(id: Id) -> String { format!( - r#"{{"jsonrpc":"2.0","error":{{"code":-32602,"message":"Invalid params"}},"id":{}}}"#, + r#"{{"jsonrpc":"2.0","id":{},"error":{{"code":-32602,"message":"Invalid params"}}}}"#, serde_json::to_string(&id).unwrap() ) } @@ -149,22 +149,22 @@ pub fn call(method: &str, params: Vec, id: Id) -> String { pub fn call_execution_failed(msg: &str, id: Id) -> String { format!( - r#"{{"jsonrpc":"2.0","error":{{"code":-32000,"message":"{}"}},"id":{}}}"#, + r#"{{"jsonrpc":"2.0","id":{},"error":{{"code":-32000,"message":"{}"}}}}"#, + serde_json::to_string(&id).unwrap(), msg, - serde_json::to_string(&id).unwrap() ) } pub fn internal_error(id: Id) -> String { format!( - r#"{{"jsonrpc":"2.0","error":{{"code":-32603,"message":"Internal error"}},"id":{}}}"#, + r#"{{"jsonrpc":"2.0","id":{},"error":{{"code":-32603,"message":"Internal error"}}}}"#, serde_json::to_string(&id).unwrap() ) } pub fn server_error(id: Id) -> String { format!( - r#"{{"jsonrpc":"2.0","error":{{"code":-32000,"message":"Server error"}},"id":{}}}"#, + r#"{{"jsonrpc":"2.0","id":{},"error":{{"code":-32000,"message":"Server error"}}}}"#, serde_json::to_string(&id).unwrap() ) } @@ -174,7 +174,7 @@ pub fn server_error(id: Id) -> String { /// NOTE: works only for one subscription because the subscription ID is hardcoded. pub fn server_subscription_id_response(id: Id) -> String { format!( - r#"{{"jsonrpc":"2.0","result":"D3wwzU6vvoUUYehv4qoFzq42DZnLoAETeFzeyk8swH4o","id":{}}}"#, + r#"{{"jsonrpc":"2.0","id":{},"result":"D3wwzU6vvoUUYehv4qoFzq42DZnLoAETeFzeyk8swH4o"}}"#, serde_json::to_string(&id).unwrap() ) } diff --git a/tests/tests/proc_macros.rs b/tests/tests/proc_macros.rs index baf5f676b5..a54554ad14 100644 --- a/tests/tests/proc_macros.rs +++ b/tests/tests/proc_macros.rs @@ -262,7 +262,7 @@ async fn macro_optional_param_parsing() { .raw_json_request(r#"{"jsonrpc":"2.0","method":"foo_optional_params","params":{"a":22,"c":50},"id":0}"#, 1) .await .unwrap(); - assert_eq!(resp, r#"{"jsonrpc":"2.0","result":"Called with: 22, None, Some(50)","id":0}"#); + assert_eq!(resp, r#"{"jsonrpc":"2.0","id":0,"result":"Called with: 22, None, Some(50)"}"#); } #[tokio::test] @@ -286,14 +286,14 @@ async fn macro_zero_copy_cow() { .unwrap(); // std::borrow::Cow always deserialized to owned variant here - assert_eq!(resp, r#"{"jsonrpc":"2.0","result":"Zero copy params: false","id":0}"#); + assert_eq!(resp, r#"{"jsonrpc":"2.0","id":0,"result":"Zero copy params: false"}"#); // serde_json will have to allocate a new string to replace `\t` with byte 0x09 (tab) let (resp, _) = module .raw_json_request(r#"{"jsonrpc":"2.0","method":"foo_zero_copy_cow","params":["\tfoo"],"id":0}"#, 1) .await .unwrap(); - assert_eq!(resp, r#"{"jsonrpc":"2.0","result":"Zero copy params: false","id":0}"#); + assert_eq!(resp, r#"{"jsonrpc":"2.0","id":0,"result":"Zero copy params: false"}"#); } // Disabled on MacOS as GH CI timings on Mac vary wildly (~100ms) making this test fail. diff --git a/tests/tests/rpc_module.rs b/tests/tests/rpc_module.rs index 1435deaae4..5c8d212bf5 100644 --- a/tests/tests/rpc_module.rs +++ b/tests/tests/rpc_module.rs @@ -383,13 +383,13 @@ async fn subscribe_unsubscribe_without_server() { let unsub_req = format!("{{\"jsonrpc\":\"2.0\",\"method\":\"my_unsub\",\"params\":[{}],\"id\":1}}", ser_id); let (resp, _) = module.raw_json_request(&unsub_req, 1).await.unwrap(); - assert_eq!(resp, r#"{"jsonrpc":"2.0","result":true,"id":1}"#); + assert_eq!(resp, r#"{"jsonrpc":"2.0","id":1,"result":true}"#); // Unsubscribe already performed; should be error. let unsub_req = format!("{{\"jsonrpc\":\"2.0\",\"method\":\"my_unsub\",\"params\":[{}],\"id\":1}}", ser_id); let (resp, _) = module.raw_json_request(&unsub_req, 2).await.unwrap(); - assert_eq!(resp, r#"{"jsonrpc":"2.0","result":false,"id":1}"#); + assert_eq!(resp, r#"{"jsonrpc":"2.0","id":1,"result":false}"#); } let sub1 = subscribe_and_assert(&module); @@ -429,7 +429,7 @@ async fn reject_works() { .unwrap(); let (rp, mut stream) = module.raw_json_request(r#"{"jsonrpc":"2.0","method":"my_sub","id":0}"#, 1).await.unwrap(); - assert_eq!(rp, r#"{"jsonrpc":"2.0","error":{"code":-32700,"message":"rejected"},"id":0}"#); + assert_eq!(rp, r#"{"jsonrpc":"2.0","id":0,"error":{"code":-32700,"message":"rejected"}}"#); assert!(stream.recv().await.is_none()); } @@ -629,7 +629,7 @@ async fn method_response_notify_on_completion() { // Low level call should also work. let (rp, _) = module.raw_json_request(r#"{"jsonrpc":"2.0","method":"hey","params":["success"],"id":0}"#, 1).await.unwrap(); - assert_eq!(rp, r#"{"jsonrpc":"2.0","result":"lo","id":0}"#); + assert_eq!(rp, r#"{"jsonrpc":"2.0","id":0,"result":"lo"}"#); assert!(matches!(rx.recv().await, Some(Ok(_)))); // Error call should return a failed notification. diff --git a/types/src/response.rs b/types/src/response.rs index bf60e911b9..c576ffa04b 100644 --- a/types/src/response.rs +++ b/types/src/response.rs @@ -327,12 +327,13 @@ where s.serialize_field("jsonrpc", field)?; } + s.serialize_field("id", &self.id)?; + match &self.payload { ResponsePayload::Error(err) => s.serialize_field("error", err)?, ResponsePayload::Success(r) => s.serialize_field("result", r)?, }; - s.serialize_field("id", &self.id)?; s.end() } } @@ -350,7 +351,7 @@ mod tests { id: Id::Number(1), }) .unwrap(); - let exp = r#"{"jsonrpc":"2.0","result":"ok","id":1}"#; + let exp = r#"{"jsonrpc":"2.0","id":1,"result":"ok"}"#; assert_eq!(ser, exp); } @@ -362,7 +363,7 @@ mod tests { id: Id::Number(1), }) .unwrap(); - let exp = r#"{"jsonrpc":"2.0","error":{"code":1,"message":"lo"},"id":1}"#; + let exp = r#"{"jsonrpc":"2.0","id":1,"error":{"code":1,"message":"lo"}}"#; assert_eq!(ser, exp); } @@ -374,7 +375,7 @@ mod tests { id: Id::Number(1), }) .unwrap(); - let exp = r#"{"result":"ok","id":1}"#; + let exp = r#"{"id":1,"result":"ok"}"#; assert_eq!(ser, exp); }