I'm currently attempting to abstract making different HTTP requests by using generics. I'm using json_serializale
for generating fromJson()
and toJson()
methods.
Here is a simple model file:
import 'package:json_annotation/json_annotation.dart';
part 'article.g.dart';
@JsonSerializable()
class Article {
int id = 0;
String title = "";
Article({this.id, this.title});
factory Article.fromJson(Map<String, dynamic> json) =>
_$ArticleFromJson(json);
Map<String, dynamic> toJson() => _$ArticleToJson(this);
}
I have a generic class that needs to be passed the fromJson
-method, see:
typedef CreateModelFromJson = dynamic Function(Map<String, dynamic> json);
class HttpGet<Model> {
CreateModelFromJson createModelFromJson;
HttpGet({
this.createModelFromJson,
});
Future<Model> do() async {
// [... make HTTP request and do stuff ...]
return createModelFromJson(jsonData);
}
}
And finally, here is the ArticleService
:
class ArticleService {
Future<Model> read() => HttpGet<Article>({
createModelFromJson: Article.fromJson,
}).do();
}
This underlines-in-red fromJson
in createModelFromJson: Article.fromJson,
, with the error being:
The getter 'fromJson' isn't defined for the class 'Article'. Try importing the library that defines 'fromJson', correcting the name to the name of an existing getter, or defining a getter or field named 'fromJson'.dart(undefined_getter)
Obviously the compiler believes .fromJson
to be a static field. However, it's, as can be seen above, a static factory method.
1.) Can you help with how to pass the constructor to the generic class?
ALSO:
2.) I'm not sure whether I'll actually get an Article
back, or if I have to type cast it first? I'm kind of worried about the dynamic
return type of the typedef
.
3.) I'm also open for better ideas for what I'm attempting to do.
As of Dart 2.15, Dart now supports constructor tear-offs. Named constructors can be used as expected. The default, unnamed constructor for a class named ClassName
can be referenced with ClassName.new
. (ClassName
by itself would be a reference to the corresponding Type
object.)
Dart 2.14 and earlier did not allow using constructors as tear-offs. For those versions, I recommend using a static
method instead.
Alternatively you could just create an explicit closure:
class ArticleService {
Future<Model> read() => HttpGet<Article>({
createModelFromJson: (json) => Article.fromJson(json),
}).do();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With