Skip to content

Commit fdc983c

Browse files
committed
codegen: enable ids to be deserialized from strings or integers
Although not strictly to spec, some upstream graphql implementations such as the start.gg API encode their ID types as integers rather than strings. Prior to this commit, deserialization would fail in such cases, since graphql_client simply type aliases the ID type to a String. This commit introduces a simple deserialization helper that enables us to handle both integers and strings while maintaining backward compatbility for downstream users. Fixes: #455 Signed-off-by: William Findlay <william@williamfindlay.com>
1 parent a7283cb commit fdc983c

File tree

3 files changed

+38
-0
lines changed

3 files changed

+38
-0
lines changed

graphql_client/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ pub use graphql_query_derive::*;
3030
))]
3131
pub mod reqwest;
3232

33+
pub mod serde_with;
34+
3335
use serde::{Deserialize, Serialize};
3436
use std::collections::HashMap;
3537
use std::fmt::{self, Display, Write};

graphql_client/src/serde_with.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//! Helpers for overriding default serde implementations.
2+
3+
use serde::{Deserialize, Deserializer};
4+
5+
/// Deserialize an optional ID type from either a String or an Integer representation.
6+
///
7+
/// This is used by the codegen to enable String IDs to be deserialized from
8+
/// either Strings or Integers.
9+
pub fn deserialize_option_id<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
10+
where
11+
D: Deserializer<'de>,
12+
{
13+
#[derive(Deserialize)]
14+
#[serde(untagged)]
15+
enum IntOrString {
16+
Int(i64),
17+
Str(String),
18+
}
19+
20+
let res = Option::<IntOrString>::deserialize(deserializer)?;
21+
22+
Ok(match res {
23+
None => None,
24+
Some(IntOrString::Int(n)) => Some(n.to_string()),
25+
Some(IntOrString::Str(s)) => Some(s),
26+
})
27+
}

graphql_client_codegen/src/codegen/selection.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,14 @@ impl<'a> ExpandedField<'a> {
405405
qualified_type
406406
};
407407

408+
let id_deserialize_with = if self.field_type == "ID" {
409+
Some(
410+
quote!(#[serde(deserialize_with = "graphql_client::serde_with::deserialize_option_id")]),
411+
)
412+
} else {
413+
None
414+
};
415+
408416
let optional_skip_serializing_none = if *options.skip_serializing_none()
409417
&& self
410418
.field_type_qualifiers
@@ -443,6 +451,7 @@ impl<'a> ExpandedField<'a> {
443451
#optional_flatten
444452
#optional_rename
445453
#optional_deprecation_annotation
454+
#id_deserialize_with
446455
pub #ident: #qualified_type
447456
};
448457

0 commit comments

Comments
 (0)