Custom constructor excludes
This commit is contained in:
parent
7c1735c113
commit
cf0a7eb652
9 changed files with 177 additions and 1 deletions
41
README.md
41
README.md
|
@ -14,6 +14,7 @@ the time you spend writing boilerplate serialization code for your models.
|
|||
* [Nesting](#nesting)
|
||||
* [ID and Date Fields](#id-and-dates)
|
||||
* [TypeScript Definition Generator](#typescript-definitions)
|
||||
* [Constructor Parameters](#constructor-parameters)
|
||||
|
||||
# Usage
|
||||
In your `pubspec.yaml`, you need to install the following dependencies:
|
||||
|
@ -252,4 +253,42 @@ interface BookCollection {
|
|||
|
||||
Fields with an `@Exclude()` that specifies `canSerialize: false` will not be present in the
|
||||
TypeScript definition. The rationale for this is that if a field (i.e. `password`) will
|
||||
never be sent to the client, the client shouldn't even know the field exists.
|
||||
never be sent to the client, the client shouldn't even know the field exists.
|
||||
|
||||
# Constructor Parameters
|
||||
Sometimes, you may need to have custom constructor parameters, for example, when
|
||||
using depedency injection frameworks. For these cases, `angel_serialize` can forward
|
||||
custom constructor parameters.
|
||||
|
||||
The following:
|
||||
```dart
|
||||
@serializable
|
||||
abstract class _Bookmark extends _BookmarkBase {
|
||||
@exclude
|
||||
final Book book;
|
||||
|
||||
int get page;
|
||||
String get comment;
|
||||
|
||||
_Bookmark(this.book);
|
||||
}
|
||||
```
|
||||
|
||||
Generates:
|
||||
|
||||
```dart
|
||||
class Bookmark extends _Bookmark {
|
||||
Bookmark(Book book,
|
||||
{this.id,
|
||||
this.page,
|
||||
this.comment,
|
||||
this.createdAt,
|
||||
this.updatedAt})
|
||||
: super(book);
|
||||
|
||||
@override
|
||||
final String id;
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
|
@ -1,5 +1,6 @@
|
|||
# 2.0.6
|
||||
* Support for using `abstract` to create immutable model classes.
|
||||
* Add support for custom constructor parameters.
|
||||
|
||||
# 2.0.5
|
||||
* Deserialization now supports un-serialized `DateTime`.
|
||||
|
|
|
@ -102,6 +102,9 @@ Future<BuildContext> buildContext(
|
|||
}
|
||||
}
|
||||
|
||||
// Get constructor params, if any
|
||||
ctx.constructorParameters.addAll(clazz.unnamedConstructor.parameters);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@ class BuildContext {
|
|||
/// The fields declared on the original class.
|
||||
final List<FieldElement> fields = [];
|
||||
|
||||
final List<ParameterElement> constructorParameters = [];
|
||||
|
||||
final ConstantReader annotation;
|
||||
|
||||
/// The name of the field that identifies data of this model type.
|
||||
|
|
|
@ -61,6 +61,18 @@ class JsonModelGenerator extends GeneratorForAnnotation<Serializable> {
|
|||
void generateConstructor(
|
||||
BuildContext ctx, ClassBuilder clazz, LibraryBuilder file) {
|
||||
clazz.constructors.add(new Constructor((constructor) {
|
||||
// Add all `super` params
|
||||
if (ctx.constructorParameters.isNotEmpty) {
|
||||
for (var param in ctx.constructorParameters) {
|
||||
constructor.requiredParameters.add(new Parameter((b) => b
|
||||
..name = param.name
|
||||
..type = convertTypeReference(param.type)));
|
||||
}
|
||||
|
||||
constructor.initializers.add(new Code(
|
||||
'super(${ctx.constructorParameters.map((p) => p.name).join(',')})'));
|
||||
}
|
||||
|
||||
for (var field in ctx.fields) {
|
||||
constructor.optionalParameters.add(new Parameter((b) {
|
||||
b
|
||||
|
@ -79,10 +91,24 @@ class JsonModelGenerator extends GeneratorForAnnotation<Serializable> {
|
|||
method
|
||||
..name = 'copyWith'
|
||||
..returns = ctx.modelClassType;
|
||||
|
||||
// Add all `super` params
|
||||
if (ctx.constructorParameters.isNotEmpty) {
|
||||
for (var param in ctx.constructorParameters) {
|
||||
method.requiredParameters.add(new Parameter((b) => b
|
||||
..name = param.name
|
||||
..type = convertTypeReference(param.type)));
|
||||
}
|
||||
}
|
||||
|
||||
var buf = new StringBuffer('return new ${ctx.modelClassName}(');
|
||||
int i = 0;
|
||||
|
||||
for (var param in ctx.constructorParameters) {
|
||||
if (i++ > 0) buf.write(', ');
|
||||
buf.write(param.name);
|
||||
}
|
||||
|
||||
// Add named parameters
|
||||
for (var field in ctx.fields) {
|
||||
method.optionalParameters.add(new Parameter((b) {
|
||||
|
|
|
@ -125,9 +125,23 @@ class SerializerGenerator extends GeneratorForAnnotation<Serializable> {
|
|||
..type = new Reference('Map')),
|
||||
);
|
||||
|
||||
// Add all `super` params
|
||||
if (ctx.constructorParameters.isNotEmpty) {
|
||||
for (var param in ctx.constructorParameters) {
|
||||
method.requiredParameters.add(new Parameter((b) => b
|
||||
..name = param.name
|
||||
..type = convertTypeReference(param.type)));
|
||||
}
|
||||
}
|
||||
|
||||
var buf = new StringBuffer('return new ${ctx.modelClassName}(');
|
||||
int i = 0;
|
||||
|
||||
for (var param in ctx.constructorParameters) {
|
||||
if (i++ > 0) buf.write(', ');
|
||||
buf.write(param.name);
|
||||
}
|
||||
|
||||
for (var field in ctx.fields) {
|
||||
if (ctx.excluded[field.name]?.canDeserialize == false) continue;
|
||||
|
||||
|
|
|
@ -26,3 +26,14 @@ abstract class _Author extends Model {
|
|||
abstract class _Library extends Model {
|
||||
Map<String, Book> get collection;
|
||||
}
|
||||
|
||||
@serializable
|
||||
abstract class _Bookmark extends Model {
|
||||
@exclude
|
||||
final Book book;
|
||||
|
||||
int get page;
|
||||
String get comment;
|
||||
|
||||
_Bookmark(this.book);
|
||||
}
|
||||
|
|
|
@ -103,3 +103,42 @@ class Library extends _Library {
|
|||
return LibrarySerializer.toMap(this);
|
||||
}
|
||||
}
|
||||
|
||||
class Bookmark extends _Bookmark {
|
||||
Bookmark(Book book,
|
||||
{this.id, this.page, this.comment, this.createdAt, this.updatedAt})
|
||||
: super(book);
|
||||
|
||||
@override
|
||||
final String id;
|
||||
|
||||
@override
|
||||
final int page;
|
||||
|
||||
@override
|
||||
final String comment;
|
||||
|
||||
@override
|
||||
final DateTime createdAt;
|
||||
|
||||
@override
|
||||
final DateTime updatedAt;
|
||||
|
||||
Bookmark copyWith(Book book,
|
||||
{String id,
|
||||
int page,
|
||||
String comment,
|
||||
DateTime createdAt,
|
||||
DateTime updatedAt}) {
|
||||
return new Bookmark(book,
|
||||
id: id ?? this.id,
|
||||
page: page ?? this.page,
|
||||
comment: comment ?? this.comment,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
updatedAt: updatedAt ?? this.updatedAt);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return BookmarkSerializer.toMap(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -107,3 +107,44 @@ abstract class LibraryFields {
|
|||
|
||||
static const String updatedAt = 'updated_at';
|
||||
}
|
||||
|
||||
abstract class BookmarkSerializer {
|
||||
static Bookmark fromMap(Map map, Book book) {
|
||||
return new Bookmark(book,
|
||||
id: map['id'],
|
||||
page: map['page'],
|
||||
comment: map['comment'],
|
||||
createdAt: map['created_at'] != null
|
||||
? (map['created_at'] is DateTime
|
||||
? map['created_at']
|
||||
: DateTime.parse(map['created_at']))
|
||||
: null,
|
||||
updatedAt: map['updated_at'] != null
|
||||
? (map['updated_at'] is DateTime
|
||||
? map['updated_at']
|
||||
: DateTime.parse(map['updated_at']))
|
||||
: null);
|
||||
}
|
||||
|
||||
static Map<String, dynamic> toMap(Bookmark model) {
|
||||
return {
|
||||
'id': model.id,
|
||||
'page': model.page,
|
||||
'comment': model.comment,
|
||||
'created_at': model.createdAt?.toIso8601String(),
|
||||
'updated_at': model.updatedAt?.toIso8601String()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
abstract class BookmarkFields {
|
||||
static const String id = 'id';
|
||||
|
||||
static const String page = 'page';
|
||||
|
||||
static const String comment = 'comment';
|
||||
|
||||
static const String createdAt = 'created_at';
|
||||
|
||||
static const String updatedAt = 'updated_at';
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue