-
-
Notifications
You must be signed in to change notification settings - Fork 119
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make GraphQLQuery JsonSerializable #62
Comments
Hello @smkhalsa! That surely seems doable and makes sense! |
@comigor awesome! Any ideas on how to implement this? I'm still a novice when it comes to code gen with build_runner. It seems that the GraphQLQuery class would need to be aware of all the generated subclasses in order to parse them correctly. |
You'll probably want to make all generated extensions of Looking at it now, the main issue is that |
Serializing the AST to a GraphQL string might be a better choice as you would be able to de-serialize / parse it even if the AST makes some incompatible changes |
Here's what you need: https://pub.dev/documentation/gql/latest/language/language-library.html |
@comigor it seems Any ideas? |
Hmm, yeah, you won't be able to serialize the function... and not having reflection don't help us at all... I thought about you creating a custom (serializable) class extending from Your custom query: @JsonSerializable()
class MySerializedQuery
extends GraphQLQuery<JsonSerializable, JsonSerializable> {
@override
JsonSerializable parse(Map<String, dynamic> json) =>
options.myConfigurationMapping[operationName](json);
@override
List<Object> get props => null;
} The configuration your user'll need to configure while instantiating your client: final client = MyGraphQLClient(
myConfigurationMapping: <String,
JsonSerializable Function(Map<String, dynamic>)>{
'operation1': MyResultClass.fromJson;
},
); Or, as an alternative, you make your client a generator ¯\(ツ)/¯ Does it make sense? |
Can't we just have the generator generate the GraphqQLQuery class and include the mapping you describe above? For example, we could store the type name as a string when calling abstract class GraphQLQuery<T, U extends JsonSerializable> extends Equatable {
///... other class members
T parse(Map<String, dynamic> json) {
switch (json) {
case json['type'] == 'MySerializedQuery':
return MySerializedQuery.parse(json);
/// other class resolvers
}
}
}
I've thought about this, and I may go in that direction eventually (I just haven't dug into code generation yet). A fully typed generated client would definitely make for a nice dev experience. |
But how are you going to persist and (more importantly) retrieve those queries? When you deserialize them, you need to have a way of knowing which type it belongs, and then it's best to have a single place where this logic will be present (and not scattered through all generated queries). Does it make sense? Or I am missing something? |
You could generate the abstract /// [generated_code]
abstract class GraphQLQuery<T, U extends JsonSerializable> extends Equatable {
///... other class members
GraphQLQuery.parse(Map<String, dynamic> json) {
switch (json) {
case json['type'] == 'MySerializedQuery':
return ExampleQuery.parse(json);
/// other class resolvers
}
}
}
class ExampleQuery extends GraphQLQuery<Example, ExampleArguments> {
/// other class members
T parse(Map<String, dynamic> json) {
/// generated parse logic for this class
}
} Then to deserialize, you'd simply do something like this: final deserializedQuery = GraphQLQuery.parse([some json object]) The parse functions of the subclasses would be ignored when serializing them. Does that make sense? |
But I disagree the abstract |
@comigor sure, that makes sense. For reference, built_value adds a "discriminator" that stores a string reference to the class name when serializing. This allows for deserializing even when you don't know the type. It may be more than we want to take on at the moment, but we could also just make queries implement built_value and get this functionality for free. |
Is there any chance this package gets a built_value implementation at this point? I'd love to use it for personal and agency projects but we're committed to the builder pattern, immutability, and out-of-the-box discriminator + serialization (including the optional plugins for things like DateTime). We find the immutability and patterning incredibly valuable so we even choose built_value and built_collection for lots of things beyond data models in our architecture, like bloc states...compared to json_serializable, the output is strictly more sound and robust data structures. |
I'm creating a GraphQL client that persists mutations when offline and runs them when the client comes back online.
I'd like to request that we make the GraphQLQuery class JsonSerializable so that we can easily persist queries for later use.
The text was updated successfully, but these errors were encountered: