I want to create several objects that are serializable to a Map
and deserializable from a Map
so I can deserialize an entire List
of such objects in other functions and methods. This is meant to avoid having to define a custom method for deserializing a List
of objects for each type but instead being able to use a single one.
abstract class Serializable {
Map<String, dynamic> toMap();
Serializable.fromMap(Map<String, dynamic> map);
}
class Schema<T extends Serializable> {
List<T> data = [];
List<Map<String, dynamic>> serialize() {
return data.map((e) => e.toMap()).toList(); // works fine
}
void deserialize(List<Map<String, dynamic>> data) {
this.data = data.map((e) => T.fromMap(e)).toList(); // fromMap is not defined for type 'Type'
}
}
This would be useful for example to store multiple objects of a class in a JSON file. As that storing part gets a bit complicated as it includes encryption I want to have a generic interface for serialization and deserialization.
class User extends Serializable {
String username;
@override
Map<String, dynamic> toMap() {
return { 'username': username};
}
@override
User.fromMap(Map<String, dynamic> map) :
username = map['username'],
}
Schema<User> users = Schema<User>();
users.deserialize(somemap);
However I cannot come up with a working solution for deserialization. If I use a generic type (that extends Serializable
) I cannot access the named constructor. Defining fromMap
as static
doesn't work as well as static methods as you can't have abstract static methods.
Is there another way for achieving multiple classes that are deserializable using a generic interface?
I solve this based on this post about Creating an instance of a generic type in DART.
typedef ItemCreator<S> = S Function(Map<String, dynamic> map);
class Schema<T extends Serializable> {
List<T> data = [];
ItemCreator<T> fromMap;
Schema(this.fromMap);
void deserialize(List<Map<String, dynamic>> data) {
this.data = data.map((e) => fromMap(e)).toList();
}
}
In this solution when constructing Schema
the .fromMap
constructor is passed.
Schema<User> users = Schema<User>(User.fromMap);