From 0b9d5ee0713f6bbccadb6d3021396a8cd4569678 Mon Sep 17 00:00:00 2001 From: sunli Date: Sun, 19 Apr 2020 10:17:47 +0800 Subject: [PATCH] The int64 scalar serializes to a string --- docs/zh-CN/src/custom_scalars.md | 33 +++++++++++++++++++++++++++++++ src/scalars/integers.rs | 34 +++++++++++++++++++++++++++++++- tests/scalars.rs | 27 +++++++++++++------------ 3 files changed, 80 insertions(+), 14 deletions(-) diff --git a/docs/zh-CN/src/custom_scalars.md b/docs/zh-CN/src/custom_scalars.md index 2e94092a..1cfb4326 100644 --- a/docs/zh-CN/src/custom_scalars.md +++ b/docs/zh-CN/src/custom_scalars.md @@ -1 +1,34 @@ # 自定义标量 + +`Async-graphql`已经内置了绝大部分常用的标量类型,同时你也能自定义标量。 + +实现`Async-graphql::Scalar`即可自定义一个标量,你只需要实现一个解析函数和输出函数。 + +下面的例子定义一个64位整数标量,但它的输入输出都是字符串。 (`Async-graphql`已经内置了对64位整数的支持,正是采用字符串作为输入输出) + +```rust +use async_graphql::*; + +struct StringNumber(i64); + +impl Scalar for StringNumber { + fn type_name() -> &'static str { + // 类型名 + "StringNumber" + } + + fn parse(value: &Value) -> Option { + if let Value::String(value) = value { + // 解析整数 + value.parse().ok() + } else { + // 类型不匹配则直接返回None + None + } + } +} + +// 这个宏必须调用 +impl_scalar!(StringNumber); + +``` \ No newline at end of file diff --git a/src/scalars/integers.rs b/src/scalars/integers.rs index 48fdd1b5..d329b55b 100644 --- a/src/scalars/integers.rs +++ b/src/scalars/integers.rs @@ -29,4 +29,36 @@ macro_rules! impl_integer_scalars { }; } -impl_integer_scalars!(i8, i16, i32, i64, u8, u16, u32, u64); +impl_integer_scalars!(i8, i16, i32, u8, u16, u32); + +macro_rules! impl_int64_scalars { + ($($ty:ty),*) => { + $( + impl Scalar for $ty { + fn type_name() -> &'static str { + "Int64" + } + + fn description() -> Option<&'static str> { + Some("The `Int64` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^64) and 2^64 - 1.") + } + + fn parse(value: &Value) -> Option { + match value { + Value::Int(n) => Some(n.as_i64().unwrap() as Self), + Value::String(s) => s.parse().ok(), + _ => None + } + } + + fn to_json(&self) -> Result { + Ok(self.to_string().into()) + } + } + + impl_scalar_internal!($ty); + )* + }; +} + +impl_int64_scalars!(i64, u64); diff --git a/tests/scalars.rs b/tests/scalars.rs index ddff4b9e..0bdfb2bf 100644 --- a/tests/scalars.rs +++ b/tests/scalars.rs @@ -1,7 +1,7 @@ use async_graphql::*; macro_rules! test_scalars { - ($test_name:ident, $ty:ty, $value:expr) => { + ($test_name:ident, $ty:ty, $value:expr, $res_value:expr) => { #[async_std::test] pub async fn $test_name() { #[InputObject] @@ -36,20 +36,21 @@ macro_rules! test_scalars { let query = format!("{{ value testArg(input: {0}) testInput(input: {{value: {0}}}) }}", json_value); assert_eq!( schema.execute(&query).await.unwrap().data, - serde_json::json!({ "value": $value, "testArg": $value, "testInput": $value }) + serde_json::json!({ "value": $res_value, "testArg": $res_value, "testInput": $res_value }) ); } }; } -test_scalars!(test_i8_scalar, i8, 10); -test_scalars!(test_i16_scalar, i16, 10); -test_scalars!(test_i32_scalar, i32, 10); -test_scalars!(test_i64_scalar, i64, 10); -test_scalars!(test_u8_scalar, u8, 10); -test_scalars!(test_u16_scalar, u16, 10); -test_scalars!(test_u32_scalar, u32, 10); -test_scalars!(test_u64_scalar, u64, 10); -test_scalars!(test_bool_scalar, bool, true); -test_scalars!(test_f32_scalar, f32, 10.5); -test_scalars!(test_f64_scalar, f32, 10.5); +test_scalars!(test_i8_scalar, i8, 10, 10); +test_scalars!(test_i16_scalar, i16, 10, 10); +test_scalars!(test_i32_scalar, i32, 10, 10); +test_scalars!(test_u8_scalar, u8, 10, 10); +test_scalars!(test_u16_scalar, u16, 10, 10); +test_scalars!(test_u32_scalar, u32, 10, 10); +test_scalars!(test_bool_scalar, bool, true, true); +test_scalars!(test_f32_scalar, f32, 10.5, 10.5); +test_scalars!(test_f64_scalar, f32, 10.5, 10.5); + +test_scalars!(test_i64_scalar, i64, 10, "10"); +test_scalars!(test_u64_scalar, u64, 10, "10");