@@ -85,15 +85,49 @@ pub struct UserId(String);
8585In case we need to customize [ resolving] [ 7 ] of a [ custom GraphQL scalar] [ 2 ] value (change the way it gets executed), the ` #[graphql(to_output_with = <fn path>)] ` attribute is the way to do so:
8686``` rust
8787# extern crate juniper;
88- # use juniper :: { GraphQLScalar , IntoValue as _, ScalarValue , Value } ;
88+ # use juniper :: GraphQLScalar ;
8989#
9090#[derive(GraphQLScalar )]
9191#[graphql(to_output_with = to_output, transparent)]
9292struct Incremented (i32 );
9393
94- /// Increments [`Incremented`] before converting into a [`Value`].
95- fn to_output <S : ScalarValue >(v : & Incremented ) -> Value <S > {
96- (v . 0 + 1 ). into_value ()
94+ fn to_output (v : & Incremented ) -> i32 {
95+ // ^^^ any concrete type having `ToScalarValue` implementation
96+ // could be used
97+ v . 0 + 1
98+ }
99+ #
100+ # fn main () {}
101+ ```
102+
103+ The provided function is polymorphic by its output type:
104+ ``` rust
105+ # extern crate jiff;
106+ # extern crate juniper;
107+ # use std :: fmt :: Display ;
108+ # use juniper :: {GraphQLScalar , ScalarValue };
109+ #
110+ #[derive(GraphQLScalar )]
111+ #[graphql(to_output_with = Self :: to_output, transparent)]
112+ struct Incremented (i32 );
113+
114+ impl Incremented {
115+ fn to_output <S : ScalarValue >(v : & Incremented ) -> S {
116+ // ^^^^^^^^^^^^^^ returning generic or concrete `ScalarValue` is also OK
117+ (v . 0 + 1 ). into ()
118+ }
119+ }
120+
121+ #[derive(GraphQLScalar )]
122+ #[graphql(to_output_with = Self :: to_output, transparent)]
123+ struct CustomDateTime (jiff :: Timestamp );
124+
125+ impl CustomDateTime {
126+ fn to_output (& self ) -> impl Display {
127+ // ^^^^^^^^^^^^ in this case macro expansion uses the
128+ // `ScalarValue::from_displayable_non_static()` conversion
129+ self . 0. strftime (" %Y-%m-%d %H:%M:%S%.fZ" )
130+ }
97131}
98132#
99133# fn main () {}
@@ -117,7 +151,7 @@ impl UserId {
117151 input : & str ,
118152 // ^^^^ any concrete type having `FromScalarValue` implementation could be used
119153 ) -> Result <Self , Box <str >> {
120- // ^^^^^^^^ must implement `IntoFieldError`
154+ // ^^^^^^^^ must implement `IntoFieldError`
121155 input
122156 . strip_prefix (" id: " )
123157 . ok_or_else (|| {
@@ -130,7 +164,7 @@ impl UserId {
130164# fn main () {}
131165```
132166
133- The provided function is polymorphic by input and output types:
167+ The provided function is polymorphic by its input and output types:
134168``` rust
135169# extern crate juniper;
136170# use juniper :: {GraphQLScalar , Scalar , ScalarValue };
@@ -169,7 +203,7 @@ Customization of which tokens a [custom GraphQL scalar][0] type should be parsed
169203``` rust
170204# extern crate juniper;
171205# use juniper :: {
172- # GraphQLScalar , ParseScalarResult , ParseScalarValue , Scalar , ScalarToken , ScalarValue , Value ,
206+ # GraphQLScalar , ParseScalarResult , ParseScalarValue , Scalar , ScalarToken , ScalarValue ,
173207# };
174208#
175209#[derive(GraphQLScalar )]
@@ -186,10 +220,12 @@ enum StringOrInt {
186220 Int (i32 ),
187221}
188222
189- fn to_output <S : ScalarValue >(v : & StringOrInt ) -> Value < S > {
223+ fn to_output <S : ScalarValue >(v : & StringOrInt ) -> S {
190224 match v {
191- StringOrInt :: String (s ) => Value :: scalar (s . to_owned ()),
192- StringOrInt :: Int (i ) => Value :: scalar (* i ),
225+ StringOrInt :: String (s ) => S :: from_displayable (s ),
226+ // ^^^^^^^^^^^^^^^^^^^ preferable conversion for types
227+ // represented by string token
228+ StringOrInt :: Int (i ) => (* i ). into (),
193229 }
194230}
195231
@@ -216,7 +252,7 @@ Instead of providing all custom functions separately, it's possible to provide a
216252``` rust
217253# extern crate juniper;
218254# use juniper :: {
219- # GraphQLScalar , ParseScalarResult , ParseScalarValue , Scalar , ScalarToken , ScalarValue , Value ,
255+ # GraphQLScalar , ParseScalarResult , ParseScalarValue , Scalar , ScalarToken , ScalarValue ,
220256# };
221257#
222258#[derive(GraphQLScalar )]
@@ -229,10 +265,10 @@ enum StringOrInt {
229265mod string_or_int {
230266 use super :: * ;
231267
232- pub (super ) fn to_output <S : ScalarValue >(v : & StringOrInt ) -> Value < S > {
268+ pub (super ) fn to_output <S : ScalarValue >(v : & StringOrInt ) -> S {
233269 match v {
234- StringOrInt :: String (s ) => Value :: scalar ( s . to_owned () ),
235- StringOrInt :: Int (i ) => Value :: scalar (* i ),
270+ StringOrInt :: String (s ) => S :: from_displayable ( s ),
271+ StringOrInt :: Int (i ) => (* i ) . into ( ),
236272 }
237273 }
238274
@@ -256,7 +292,7 @@ A regular `impl` block is also suitable for that:
256292``` rust
257293# extern crate juniper;
258294# use juniper :: {
259- # GraphQLScalar , ParseScalarResult , ParseScalarValue , Scalar , ScalarToken , ScalarValue , Value ,
295+ # GraphQLScalar , ParseScalarResult , ParseScalarValue , Scalar , ScalarToken , ScalarValue ,
260296# };
261297#
262298#[derive(GraphQLScalar )]
@@ -267,10 +303,10 @@ enum StringOrInt {
267303}
268304
269305impl StringOrInt {
270- fn to_output <S : ScalarValue >(& self ) -> Value < S > {
306+ fn to_output <S : ScalarValue >(& self ) -> S {
271307 match self {
272- Self :: String (s ) => Value :: scalar ( s . to_owned () ),
273- Self :: Int (i ) => Value :: scalar (* i ),
308+ Self :: String (s ) => S :: from_displayable ( s ),
309+ Self :: Int (i ) => (* i ) . into ( ),
274310 }
275311 }
276312
@@ -297,7 +333,7 @@ At the same time, any custom function still may be specified separately, if requ
297333``` rust
298334# extern crate juniper;
299335# use juniper :: {
300- # GraphQLScalar , ParseScalarResult , Scalar , ScalarToken , ScalarValue , Value ,
336+ # GraphQLScalar , ParseScalarResult , Scalar , ScalarToken , ScalarValue ,
301337# };
302338#
303339#[derive(GraphQLScalar )]
@@ -313,13 +349,10 @@ enum StringOrInt {
313349mod string_or_int {
314350 use super :: * ;
315351
316- pub (super ) fn to_output <S >(v : & StringOrInt ) -> Value <S >
317- where
318- S : ScalarValue ,
319- {
352+ pub (super ) fn to_output <S : ScalarValue >(v : & StringOrInt ) -> S {
320353 match v {
321- StringOrInt :: String (s ) => Value :: scalar ( s . to_owned () ),
322- StringOrInt :: Int (i ) => Value :: scalar (* i ),
354+ StringOrInt :: String (s ) => S :: from_displayable ( s ),
355+ StringOrInt :: Int (i ) => (* i ) . into ( ),
323356 }
324357 }
325358
@@ -367,11 +400,12 @@ For implementing [custom scalars][2] on foreign types there is [`#[graphql_scala
367400# }
368401#
369402# use juniper :: DefaultScalarValue as CustomScalarValue ;
370- use juniper :: {ScalarValue , Value , graphql_scalar};
403+ use juniper :: {ScalarValue , graphql_scalar};
371404
372405#[graphql_scalar]
373406#[graphql(
374407 with = date_scalar,
408+ to_output_with = ScalarValue :: from_displayable, // use `Display` representation
375409 parse_token(String ),
376410 scalar = CustomScalarValue ,
377411)]
@@ -381,10 +415,6 @@ type Date = date::Date;
381415
382416mod date_scalar {
383417 use super :: * ;
384-
385- pub (super ) fn to_output (v : & Date ) -> Value <CustomScalarValue > {
386- Value :: scalar (v . to_string ())
387- }
388418
389419 pub (super ) fn from_input (s : & str ) -> Result <Date , Box <str >> {
390420 s . parse (). map_err (| e | format! (" Failed to parse `Date`: {e}" ). into ())
0 commit comments