gen 2.2.0

This commit is contained in:
Tobe O 2018-12-08 15:53:49 -05:00
parent 60f36206fb
commit 66006ecf5b
25 changed files with 570 additions and 505 deletions

107
README.md
View file

@ -1,4 +1,5 @@
# serialize
[![Pub](https://img.shields.io/pub/v/angel_serialize.svg)](https://pub.dartlang.org/packages/angel_serialize)
[![build status](https://travis-ci.org/angel-dart/serialize.svg)](https://travis-ci.org/angel-dart/serialize)
@ -6,26 +7,29 @@ Source-generated serialization for Dart objects. This package uses `package:sour
the time you spend writing boilerplate serialization code for your models.
`package:angel_serialize` also powers `package:angel_orm`.
* [Usage](#usage)
* [Models](#models)
* [Field Aliases](#aliases)
* [Excluding Keys](#excluding-keys)
* [Required Fields](#required-fields)
* [Serialization](#serializaition)
* [Nesting](#nesting)
* [ID and Date Fields](#id-and-dates)
* [TypeScript Definition Generator](#typescript-definitions)
* [Constructor Parameters](#constructor-parameters)
- [Usage](#usage)
- [Models](#models)
- [Field Aliases](#aliases)
- [Excluding Keys](#excluding-keys)
- [Required Fields](#required-fields)
- [Serialization](#serializaition)
- [Nesting](#nesting)
- [ID and Date Fields](#id-and-dates)
- [Binary Data](#binary-data)
- [TypeScript Definition Generator](#typescript-definitions)
- [Constructor Parameters](#constructor-parameters)
# Usage
In your `pubspec.yaml`, you need to install the following dependencies:
```yaml
dependencies:
angel_model: ^1.0.0 # Only required if using Angel!!!
angel_model: ^1.0.0
angel_serialize: ^2.0.0
dev_dependencies:
angel_serialize_generator: ^2.0.0
build_runner: ^0.8.0
build_runner: ^1.0.0
```
With the recent updates to `package:build_runner`, you can build models in
@ -38,6 +42,7 @@ If you want to watch for file changes and re-build when necessary, replace the `
with a call to `watch`. They take the same parameters.
# Models
There are a few changes opposed to normal Model classes. You need to add a `@serializable` annotation to your model
class to have it serialized, and a serializable model class's name should also start
with a leading underscore.
@ -61,13 +66,13 @@ part 'book.g.dart';
@serializable
abstract class _Book extends Model {
String get author;
String get title;
String get description;
int get pageCount;
BookType get type;
}
@ -78,17 +83,18 @@ enum BookType {
}
```
The following files will be generated:
* `book.g.dart`
* `book.serializer.g.dart`
The following file will be generated:
- `book.g.dart`
Producing these classes:
* `Book`: Extends or implements `_Book`; may be `const`-enabled.
* `BookSerializer`: static functionality for serializing `Book` models.
* `BookFields`: The names of all fields from the `Book` model, statically-available.
- `Book`: Extends or implements `_Book`; may be `const`-enabled.
- `BookSerializer`: static functionality for serializing `Book` models.
- `BookFields`: The names of all fields from the `Book` model, statically-available.
# Serialization
You can use the generated files as follows:
```dart
@ -99,18 +105,18 @@ myFunction() {
description: 'You will cry after reading this.',
pageCount: 1225
);
// Easily serialize models into Maps
var map = BookSerializer.toMap(warAndPeace);
// Also deserialize from Maps
var book = BookSerializer.fromMap(map);
print(book.title); // 'War and Peace'
// For compatibility with `JSON.encode`, a `toJson` method
// is included that forwards to `BookSerializer.toMap`:
expect(book.toJson(), map);
// Generated classes act as value types, and thus can be compared.
expect(BookSerializer.fromMap(map), equals(warAndPeace));
}
@ -126,12 +132,15 @@ about the serialized names of keys on your model class.
}
}
```
## Customizing Serialization
Currently, these serialization methods are supported:
* to `Map`
* to JSON
* to TypeScript definitions
- to `Map`
- to JSON
- to TypeScript definitions
You can customize these by means of `serializers`:
```dart
@ -139,8 +148,8 @@ You can customize these by means of `serializers`:
class _MyClass extends Model {}
```
## Aliases
Whereas Dart fields conventionally are camelCased, most database columns
tend to be snake_cased. This is not a problem, because we can define an alias
for a field.
@ -152,13 +161,13 @@ provide a custom name, or pass `autoSnakeCaseNames`: `false` to the builder;
@serializable
abstract class _Spy extends Model {
/// Will show up as 'agency_id' in serialized JSON.
///
///
/// When deserializing JSON, instead of searching for an 'agencyId' key,
/// it will use 'agency_id'.
///
///
/// Hooray!
String agencyId;
@Alias('foo')
String someOtherField;
}
@ -174,6 +183,7 @@ abstract class _OtherCasing extends Model {
```
## Excluding Keys
In pratice, there may keys that you want to exclude from JSON.
To accomplish this, simply annotate them with `@exclude`:
@ -196,7 +206,7 @@ In this case, use `canSerialize` or `canDeserialize`:
@serializable
abstract class _Whisper extends Model {
/// Will never be serialized to JSON
///
///
/// ... But it can be deserialized
@Exclude(canDeserialize: true)
String secret;
@ -204,6 +214,7 @@ abstract class _Whisper extends Model {
```
## Required Fields
It is easy to mark a field as required; just use the
`@required` annotation from `package:meta`:
@ -212,7 +223,7 @@ It is easy to mark a field as required; just use the
abstract class _Foo extends Model {
@required
int myRequiredInt;
@Required('Custom message')
int myOtherRequiredInt;
}
@ -223,10 +234,12 @@ generated constructor, and serializers will check for its
presence, throwing a `FormatException` if it is missing.
# Nesting
`angel_serialize` also supports a few types of nesting of `@serializable` classes:
* As a class member, ex. `Book myField`
* As the type argument to a `List`, ex. `List<Book>`
* As the second type argument to a `Map`, ex. `Map<String, Book>`
- As a class member, ex. `Book myField`
- As the type argument to a `List`, ex. `List<Book>`
- As the second type argument to a `Map`, ex. `Map<String, Book>`
In other words, the following are all legal, and will be serialized/deserialized.
You can use either the underscored name of a child class (ex. `_Book`), or the
@ -246,11 +259,11 @@ then you will need to generate `book.g.dart` before, `author.g.dart`,
**in a separate build action**. This way, the analyzer can resolve the `Book` type.
# ID and Dates
This package will automatically generate `id`, `createdAt`, and `updatedAt` fields for you,
in the style of an Angel `Model`. To disable this, set `autoIdAndDateFields` to `false` in the
builder constructor.
You can also override `autoIdAndDateFields` per model:
```dart
@ -258,7 +271,13 @@ You can also override `autoIdAndDateFields` per model:
abstract class _Skinny extends Model {}
```
# Binary Data
`package:angel_serialize` also handles `Uint8List` fields, by means of serialization to
and from `base64` encoding.
# TypeScript Definitions
It is quite common to build frontends with JavaScript and/or TypeScript,
so why not generate typings as well?
@ -297,11 +316,13 @@ TypeScript definition. The rationale for this is that if a field (i.e. `password
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 {

View file

@ -1,3 +1,9 @@
# 2.2.0
* Build to `cache`.
* Only generate one `.g.dart` file.
* Support for `Uint8List`.
* Use `.cast()` for `List`s and `Map`s of *non-`Model`* types.
# 2.1.2
* Add `declare module` to generated TypeScript files.

View file

@ -7,13 +7,14 @@ builders:
- serializerBuilder
- typescriptDefinitionBuilder
auto_apply: root_package
build_to: source
build_to: cache
build_extensions:
.dart:
- "angel_serialize.g.part"
- ".serializer.g.dart"
- "angel_serialize_serializer.g.part"
- ".d.ts"
applies_builders: ["source_gen|combining_builder", "source_gen|part_cleanup"]
runs_before: ["angel_orm_generator|angel_orm"]
targets:
_book:
sources:

View file

@ -1,6 +1,7 @@
library angel_serialize_generator;
import 'dart:async';
import 'dart:typed_data';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
@ -28,10 +29,8 @@ Builder jsonModelBuilder(_) {
}
Builder serializerBuilder(_) {
return new PartBuilder(
const [const SerializerGenerator()],
'.serializer.g.dart',
);
return new SharedPartBuilder(
const [const SerializerGenerator()], 'angel_serialize_serializer');
}
Builder typescriptDefinitionBuilder(_) {
@ -73,8 +72,9 @@ bool isModelClass(DartType t) {
}
bool isListOrMapType(DartType t) {
return const TypeChecker.fromRuntime(List).isAssignableFromType(t) ||
const TypeChecker.fromRuntime(Map).isAssignableFromType(t);
return (const TypeChecker.fromRuntime(List).isAssignableFromType(t) ||
const TypeChecker.fromRuntime(Map).isAssignableFromType(t)) &&
!const TypeChecker.fromRuntime(Uint8List).isAssignableFromType(t);
}
bool isEnumType(DartType t) {

View file

@ -180,7 +180,7 @@ class JsonModelGenerator extends GeneratorForAnnotation<Serializable> {
var eq = generateEquality(type.typeArguments[0]);
return 'const ListEquality<${type.typeArguments[0].name}>($eq)';
} else
return 'const ListEquality<${type.typeArguments[0].name}>()';
return 'const ListEquality()';
} else if (const TypeChecker.fromRuntime(Map)
.isAssignableFromType(type)) {
if (type.typeParameters.length == 2) {
@ -188,7 +188,7 @@ class JsonModelGenerator extends GeneratorForAnnotation<Serializable> {
veq = generateEquality(type.typeArguments[1]);
return 'const MapEquality<${type.typeArguments[0].name}, ${type.typeArguments[1].name}>(keys: $keq, values: $veq)';
} else
return 'const MapEquality()<${type.typeArguments[0].name}, ${type.typeArguments[1].name}>';
return 'const MapEquality()';
}
return nullable ? null : 'const DefaultEquality<${type.name}>()';

View file

@ -128,6 +128,13 @@ class SerializerGenerator extends GeneratorForAnnotation<Serializable> {
null
: ${t.name}.values.indexOf(model.${field.name})
''';
} else if (const TypeChecker.fromRuntime(Uint8List)
.isAssignableFromType(t)) {
serializedRepresentation = '''
model.${field.name} == null ?
null
: base64.encode(model.${field.name})
''';
}
}
@ -237,6 +244,45 @@ class SerializerGenerator extends GeneratorForAnnotation<Serializable> {
: null
)
''';
} else if (const TypeChecker.fromRuntime(List)
.isAssignableFromType(t) &&
t.typeArguments.length == 1) {
var arg = convertTypeReference(t.typeArguments[0])
.accept(new DartEmitter());
deserializedRepresentation = '''
map['$alias'] is Iterable
? (map['$alias'] as Iterable).cast<$arg>().toList()
: null
''';
} else if (const TypeChecker.fromRuntime(Map)
.isAssignableFromType(t) &&
t.typeArguments.length == 2) {
var key = convertTypeReference(t.typeArguments[0])
.accept(new DartEmitter());
var value = convertTypeReference(t.typeArguments[1])
.accept(new DartEmitter());
deserializedRepresentation = '''
map['$alias'] is Map
? (map['$alias'] as Map).cast<$key, $value>()
: null
''';
} else if (const TypeChecker.fromRuntime(Uint8List)
.isAssignableFromType(t)) {
deserializedRepresentation = '''
map['$alias'] is Uint8List
? (map['$alias'] as Uint8List)
:
(
map['$alias'] is Iterable<int>
? new Uint8List.fromList((map['$alias'] as Iterable<int>).toList())
:
(
map['$alias'] is String
? new Uint8List.fromList(base64.decode(map['$alias'] as String))
: null
)
)
''';
}
}

View file

@ -1,5 +1,5 @@
name: angel_serialize_generator
version: 2.1.2
version: 2.2.0
description: Model serialization generators, designed for use with Angel. Combine with angel_serialize for flexible modeling.
author: Tobe O <thosakwe@gmail.com>
homepage: https://github.com/angel-dart/serialize
@ -7,7 +7,7 @@ environment:
sdk: '>=2.0.0-dev.55 <3.0.0'
dependencies:
angel_model: ^1.0.0
angel_serialize: ^2.0.0-alpha
angel_serialize: ^2.0.0
build_config: ">=0.3.0 <2.0.0"
code_buffer: ^1.0.0
code_builder: ^3.0.0

View file

@ -1,3 +1,5 @@
import 'dart:typed_data';
import 'package:test/test.dart';
import 'models/with_enum.dart';
@ -45,4 +47,15 @@ void main() {
test('const', () {
expect(identical(aWithEnum, aWithEnum2), true);
});
test('uint8list', () {
var ee = new WithEnum(
imageBytes:
new Uint8List.fromList(new List<int>.generate(1000, (i) => i)));
var eeMap = ee.toJson();
print(eeMap);
var ef = WithEnumSerializer.fromMap(eeMap);
expect(ee.copyWith(), ee);
expect(ef, ee);
});
}

View file

@ -1,21 +0,0 @@
/// <reference path="./book.d.ts" />
// GENERATED CODE - DO NOT MODIFY BY HAND
declare module 'angel_serialize_generator' {
interface Library {
id?: string;
collection?: LibraryCollection;
created_at?: any;
updated_at?: any;
}
interface LibraryCollection {
[key: string]: Book;
}
interface Bookmark {
id?: string;
history?: number[];
page: number;
comment?: string;
created_at?: any;
updated_at?: any;
}
}

View file

@ -5,11 +5,8 @@ import 'package:angel_serialize/angel_serialize.dart';
import 'package:collection/collection.dart';
import 'package:meta/meta.dart';
import 'book.dart';
part 'author.g.dart';
part 'author.serializer.g.dart';
@serializable
abstract class _Author extends Model {
@required

View file

@ -220,3 +220,221 @@ class Bookmark extends _Bookmark {
return BookmarkSerializer.toMap(this);
}
}
// **************************************************************************
// SerializerGenerator
// **************************************************************************
abstract class AuthorSerializer {
static Author fromMap(Map map) {
if (map['name'] == null) {
throw new FormatException("Missing required field 'name' on Author.");
}
if (map['age'] == null) {
throw new FormatException("Custom message for missing `age`");
}
return new Author(
id: map['id'] as String,
name: map['name'] as String,
age: map['age'] as int,
books: map['books'] is Iterable
? new List.unmodifiable(((map['books'] as Iterable)
.where((x) => x is Map) as Iterable<Map>)
.map(BookSerializer.fromMap))
: null,
newestBook: map['newest_book'] != null
? BookSerializer.fromMap(map['newest_book'] as Map)
: null,
obscured: map['obscured'] as String,
createdAt: map['created_at'] != null
? (map['created_at'] is DateTime
? (map['created_at'] as DateTime)
: DateTime.parse(map['created_at'].toString()))
: null,
updatedAt: map['updated_at'] != null
? (map['updated_at'] is DateTime
? (map['updated_at'] as DateTime)
: DateTime.parse(map['updated_at'].toString()))
: null);
}
static Map<String, dynamic> toMap(Author model) {
if (model == null) {
return null;
}
if (model.name == null) {
throw new FormatException("Missing required field 'name' on Author.");
}
if (model.age == null) {
throw new FormatException("Custom message for missing `age`");
}
return {
'id': model.id,
'name': model.name,
'age': model.age,
'books': model.books?.map((m) => m.toJson())?.toList(),
'newest_book': BookSerializer.toMap(model.newestBook),
'created_at': model.createdAt?.toIso8601String(),
'updated_at': model.updatedAt?.toIso8601String()
};
}
}
abstract class AuthorFields {
static const List<String> allFields = const <String>[
id,
name,
age,
books,
newestBook,
secret,
obscured,
createdAt,
updatedAt
];
static const String id = 'id';
static const String name = 'name';
static const String age = 'age';
static const String books = 'books';
static const String newestBook = 'newest_book';
static const String secret = 'secret';
static const String obscured = 'obscured';
static const String createdAt = 'created_at';
static const String updatedAt = 'updated_at';
}
abstract class LibrarySerializer {
static Library fromMap(Map map) {
return new Library(
id: map['id'] as String,
collection: map['collection'] is Map
? new Map.unmodifiable(
(map['collection'] as Map).keys.fold({}, (out, key) {
return out
..[key] = BookSerializer.fromMap(
((map['collection'] as Map)[key]) as Map);
}))
: null,
createdAt: map['created_at'] != null
? (map['created_at'] is DateTime
? (map['created_at'] as DateTime)
: DateTime.parse(map['created_at'].toString()))
: null,
updatedAt: map['updated_at'] != null
? (map['updated_at'] is DateTime
? (map['updated_at'] as DateTime)
: DateTime.parse(map['updated_at'].toString()))
: null);
}
static Map<String, dynamic> toMap(Library model) {
if (model == null) {
return null;
}
return {
'id': model.id,
'collection': model.collection.keys?.fold({}, (map, key) {
return map..[key] = BookSerializer.toMap(model.collection[key]);
}),
'created_at': model.createdAt?.toIso8601String(),
'updated_at': model.updatedAt?.toIso8601String()
};
}
}
abstract class LibraryFields {
static const List<String> allFields = const <String>[
id,
collection,
createdAt,
updatedAt
];
static const String id = 'id';
static const String collection = 'collection';
static const String createdAt = 'created_at';
static const String updatedAt = 'updated_at';
}
abstract class BookmarkSerializer {
static Bookmark fromMap(Map map, Book book) {
if (map['page'] == null) {
throw new FormatException("Missing required field 'page' on Bookmark.");
}
return new Bookmark(book,
id: map['id'] as String,
history: map['history'] is Iterable
? (map['history'] as Iterable).cast<int>().toList()
: null,
page: map['page'] as int,
comment: map['comment'] as String,
createdAt: map['created_at'] != null
? (map['created_at'] is DateTime
? (map['created_at'] as DateTime)
: DateTime.parse(map['created_at'].toString()))
: null,
updatedAt: map['updated_at'] != null
? (map['updated_at'] is DateTime
? (map['updated_at'] as DateTime)
: DateTime.parse(map['updated_at'].toString()))
: null);
}
static Map<String, dynamic> toMap(Bookmark model) {
if (model == null) {
return null;
}
if (model.page == null) {
throw new FormatException("Missing required field 'page' on Bookmark.");
}
return {
'id': model.id,
'history': model.history,
'page': model.page,
'comment': model.comment,
'created_at': model.createdAt?.toIso8601String(),
'updated_at': model.updatedAt?.toIso8601String()
};
}
}
abstract class BookmarkFields {
static const List<String> allFields = const <String>[
id,
history,
page,
comment,
createdAt,
updatedAt
];
static const String id = 'id';
static const String history = 'history';
static const String page = 'page';
static const String comment = 'comment';
static const String createdAt = 'created_at';
static const String updatedAt = 'updated_at';
}

View file

@ -1,219 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of angel_serialize.test.models.author;
// **************************************************************************
// SerializerGenerator
// **************************************************************************
abstract class AuthorSerializer {
static Author fromMap(Map map) {
if (map['name'] == null) {
throw new FormatException("Missing required field 'name' on Author.");
}
if (map['age'] == null) {
throw new FormatException("Custom message for missing `age`");
}
return new Author(
id: map['id'] as String,
name: map['name'] as String,
age: map['age'] as int,
books: map['books'] is Iterable
? new List.unmodifiable(((map['books'] as Iterable)
.where((x) => x is Map) as Iterable<Map>)
.map(BookSerializer.fromMap))
: null,
newestBook: map['newest_book'] != null
? BookSerializer.fromMap(map['newest_book'] as Map)
: null,
obscured: map['obscured'] as String,
createdAt: map['created_at'] != null
? (map['created_at'] is DateTime
? (map['created_at'] as DateTime)
: DateTime.parse(map['created_at'].toString()))
: null,
updatedAt: map['updated_at'] != null
? (map['updated_at'] is DateTime
? (map['updated_at'] as DateTime)
: DateTime.parse(map['updated_at'].toString()))
: null);
}
static Map<String, dynamic> toMap(Author model) {
if (model == null) {
return null;
}
if (model.name == null) {
throw new FormatException("Missing required field 'name' on Author.");
}
if (model.age == null) {
throw new FormatException("Custom message for missing `age`");
}
return {
'id': model.id,
'name': model.name,
'age': model.age,
'books': model.books?.map((m) => m.toJson())?.toList(),
'newest_book': BookSerializer.toMap(model.newestBook),
'created_at': model.createdAt?.toIso8601String(),
'updated_at': model.updatedAt?.toIso8601String()
};
}
}
abstract class AuthorFields {
static const List<String> allFields = const <String>[
id,
name,
age,
books,
newestBook,
secret,
obscured,
createdAt,
updatedAt
];
static const String id = 'id';
static const String name = 'name';
static const String age = 'age';
static const String books = 'books';
static const String newestBook = 'newest_book';
static const String secret = 'secret';
static const String obscured = 'obscured';
static const String createdAt = 'created_at';
static const String updatedAt = 'updated_at';
}
abstract class LibrarySerializer {
static Library fromMap(Map map) {
return new Library(
id: map['id'] as String,
collection: map['collection'] is Map
? new Map.unmodifiable(
(map['collection'] as Map).keys.fold({}, (out, key) {
return out
..[key] = BookSerializer.fromMap(
((map['collection'] as Map)[key]) as Map);
}))
: null,
createdAt: map['created_at'] != null
? (map['created_at'] is DateTime
? (map['created_at'] as DateTime)
: DateTime.parse(map['created_at'].toString()))
: null,
updatedAt: map['updated_at'] != null
? (map['updated_at'] is DateTime
? (map['updated_at'] as DateTime)
: DateTime.parse(map['updated_at'].toString()))
: null);
}
static Map<String, dynamic> toMap(Library model) {
if (model == null) {
return null;
}
return {
'id': model.id,
'collection': model.collection.keys?.fold({}, (map, key) {
return map..[key] = BookSerializer.toMap(model.collection[key]);
}),
'created_at': model.createdAt?.toIso8601String(),
'updated_at': model.updatedAt?.toIso8601String()
};
}
}
abstract class LibraryFields {
static const List<String> allFields = const <String>[
id,
collection,
createdAt,
updatedAt
];
static const String id = 'id';
static const String collection = 'collection';
static const String createdAt = 'created_at';
static const String updatedAt = 'updated_at';
}
abstract class BookmarkSerializer {
static Bookmark fromMap(Map map, Book book) {
if (map['page'] == null) {
throw new FormatException("Missing required field 'page' on Bookmark.");
}
return new Bookmark(book,
id: map['id'] as String,
history: map['history'] as List<int>,
page: map['page'] as int,
comment: map['comment'] as String,
createdAt: map['created_at'] != null
? (map['created_at'] is DateTime
? (map['created_at'] as DateTime)
: DateTime.parse(map['created_at'].toString()))
: null,
updatedAt: map['updated_at'] != null
? (map['updated_at'] is DateTime
? (map['updated_at'] as DateTime)
: DateTime.parse(map['updated_at'].toString()))
: null);
}
static Map<String, dynamic> toMap(Bookmark model) {
if (model == null) {
return null;
}
if (model.page == null) {
throw new FormatException("Missing required field 'page' on Bookmark.");
}
return {
'id': model.id,
'history': model.history,
'page': model.page,
'comment': model.comment,
'created_at': model.createdAt?.toIso8601String(),
'updated_at': model.updatedAt?.toIso8601String()
};
}
}
abstract class BookmarkFields {
static const List<String> allFields = const <String>[
id,
history,
page,
comment,
createdAt,
updatedAt
];
static const String id = 'id';
static const String history = 'history';
static const String page = 'page';
static const String comment = 'comment';
static const String createdAt = 'created_at';
static const String updatedAt = 'updated_at';
}

View file

@ -1,14 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
declare module 'angel_serialize_generator' {
interface Book {
id?: string;
author?: string;
title?: string;
description?: string;
page_count?: number;
not_models?: number[];
camelCase?: string;
created_at?: any;
updated_at?: any;
}
}

View file

@ -4,7 +4,6 @@ import 'package:angel_model/angel_model.dart';
import 'package:angel_serialize/angel_serialize.dart';
import 'package:collection/collection.dart';
part 'book.g.dart';
part 'book.serializer.g.dart';
@Serializable(serializers: Serializers.all)
abstract class _Book extends Model {

View file

@ -102,3 +102,81 @@ class Book extends _Book {
return BookSerializer.toMap(this);
}
}
// **************************************************************************
// SerializerGenerator
// **************************************************************************
abstract class BookSerializer {
static Book fromMap(Map map) {
return new Book(
id: map['id'] as String,
author: map['author'] as String,
title: map['title'] as String,
description: map['description'] as String,
pageCount: map['page_count'] as int,
notModels: map['not_models'] is Iterable
? (map['not_models'] as Iterable).cast<double>().toList()
: null,
camelCaseString: map['camelCase'] as String,
createdAt: map['created_at'] != null
? (map['created_at'] is DateTime
? (map['created_at'] as DateTime)
: DateTime.parse(map['created_at'].toString()))
: null,
updatedAt: map['updated_at'] != null
? (map['updated_at'] is DateTime
? (map['updated_at'] as DateTime)
: DateTime.parse(map['updated_at'].toString()))
: null);
}
static Map<String, dynamic> toMap(Book model) {
if (model == null) {
return null;
}
return {
'id': model.id,
'author': model.author,
'title': model.title,
'description': model.description,
'page_count': model.pageCount,
'not_models': model.notModels,
'camelCase': model.camelCaseString,
'created_at': model.createdAt?.toIso8601String(),
'updated_at': model.updatedAt?.toIso8601String()
};
}
}
abstract class BookFields {
static const List<String> allFields = const <String>[
id,
author,
title,
description,
pageCount,
notModels,
camelCaseString,
createdAt,
updatedAt
];
static const String id = 'id';
static const String author = 'author';
static const String title = 'title';
static const String description = 'description';
static const String pageCount = 'page_count';
static const String notModels = 'not_models';
static const String camelCaseString = 'camelCase';
static const String createdAt = 'created_at';
static const String updatedAt = 'updated_at';
}

View file

@ -1,79 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of angel_serialize.test.models.book;
// **************************************************************************
// SerializerGenerator
// **************************************************************************
abstract class BookSerializer {
static Book fromMap(Map map) {
return new Book(
id: map['id'] as String,
author: map['author'] as String,
title: map['title'] as String,
description: map['description'] as String,
pageCount: map['page_count'] as int,
notModels: map['not_models'] as List<double>,
camelCaseString: map['camelCase'] as String,
createdAt: map['created_at'] != null
? (map['created_at'] is DateTime
? (map['created_at'] as DateTime)
: DateTime.parse(map['created_at'].toString()))
: null,
updatedAt: map['updated_at'] != null
? (map['updated_at'] is DateTime
? (map['updated_at'] as DateTime)
: DateTime.parse(map['updated_at'].toString()))
: null);
}
static Map<String, dynamic> toMap(Book model) {
if (model == null) {
return null;
}
return {
'id': model.id,
'author': model.author,
'title': model.title,
'description': model.description,
'page_count': model.pageCount,
'not_models': model.notModels,
'camelCase': model.camelCaseString,
'created_at': model.createdAt?.toIso8601String(),
'updated_at': model.updatedAt?.toIso8601String()
};
}
}
abstract class BookFields {
static const List<String> allFields = const <String>[
id,
author,
title,
description,
pageCount,
notModels,
camelCaseString,
createdAt,
updatedAt
];
static const String id = 'id';
static const String author = 'author';
static const String title = 'title';
static const String description = 'description';
static const String pageCount = 'page_count';
static const String notModels = 'not_models';
static const String camelCaseString = 'camelCase';
static const String createdAt = 'created_at';
static const String updatedAt = 'updated_at';
}

View file

@ -1,10 +1,8 @@
import 'package:angel_serialize/angel_serialize.dart';
import 'package:collection/collection.dart';
import 'game_pad_button.dart';
part 'game_pad.g.dart';
part 'game_pad.serializer.g.dart';
@Serializable(autoIdAndDateFields: false)
class _Gamepad {

View file

@ -45,3 +45,39 @@ class Gamepad extends _Gamepad {
return GamepadSerializer.toMap(this);
}
}
// **************************************************************************
// SerializerGenerator
// **************************************************************************
abstract class GamepadSerializer {
static Gamepad fromMap(Map map) {
return new Gamepad(
buttons: map['buttons'] is Iterable
? new List.unmodifiable(((map['buttons'] as Iterable)
.where((x) => x is Map) as Iterable<Map>)
.map(GamepadButtonSerializer.fromMap))
: null,
dynamicMap: map['dynamic_map'] is Map
? (map['dynamic_map'] as Map).cast<String, dynamic>()
: null);
}
static Map<String, dynamic> toMap(Gamepad model) {
if (model == null) {
return null;
}
return {
'buttons': model.buttons?.map((m) => m.toJson())?.toList(),
'dynamic_map': model.dynamicMap
};
}
}
abstract class GamepadFields {
static const List<String> allFields = const <String>[buttons, dynamicMap];
static const String buttons = 'buttons';
static const String dynamicMap = 'dynamic_map';
}

View file

@ -1,37 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'game_pad.dart';
// **************************************************************************
// SerializerGenerator
// **************************************************************************
abstract class GamepadSerializer {
static Gamepad fromMap(Map map) {
return new Gamepad(
buttons: map['buttons'] is Iterable
? new List.unmodifiable(((map['buttons'] as Iterable)
.where((x) => x is Map) as Iterable<Map>)
.map(GamepadButtonSerializer.fromMap))
: null,
dynamicMap: map['dynamic_map'] as Map<String, dynamic>);
}
static Map<String, dynamic> toMap(Gamepad model) {
if (model == null) {
return null;
}
return {
'buttons': model.buttons?.map((m) => m.toJson())?.toList(),
'dynamic_map': model.dynamicMap
};
}
}
abstract class GamepadFields {
static const List<String> allFields = const <String>[buttons, dynamicMap];
static const String buttons = 'buttons';
static const String dynamicMap = 'dynamic_map';
}

View file

@ -1,6 +1,5 @@
import 'package:angel_serialize/angel_serialize.dart';
part 'game_pad_button.g.dart';
part 'game_pad_button.serializer.g.dart';
@Serializable(autoIdAndDateFields: false)
abstract class _GamepadButton {

View file

@ -36,3 +36,29 @@ class GamepadButton implements _GamepadButton {
return GamepadButtonSerializer.toMap(this);
}
}
// **************************************************************************
// SerializerGenerator
// **************************************************************************
abstract class GamepadButtonSerializer {
static GamepadButton fromMap(Map map) {
return new GamepadButton(
name: map['name'] as String, radius: map['radius'] as int);
}
static Map<String, dynamic> toMap(GamepadButton model) {
if (model == null) {
return null;
}
return {'name': model.name, 'radius': model.radius};
}
}
abstract class GamepadButtonFields {
static const List<String> allFields = const <String>[name, radius];
static const String name = 'name';
static const String radius = 'radius';
}

View file

@ -1,29 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'game_pad_button.dart';
// **************************************************************************
// SerializerGenerator
// **************************************************************************
abstract class GamepadButtonSerializer {
static GamepadButton fromMap(Map map) {
return new GamepadButton(
name: map['name'] as String, radius: map['radius'] as int);
}
static Map<String, dynamic> toMap(GamepadButton model) {
if (model == null) {
return null;
}
return {'name': model.name, 'radius': model.radius};
}
}
abstract class GamepadButtonFields {
static const List<String> allFields = const <String>[name, radius];
static const String name = 'name';
static const String radius = 'radius';
}

View file

@ -1,13 +1,16 @@
import 'dart:convert';
import 'dart:typed_data';
import 'package:angel_serialize/angel_serialize.dart';
import 'package:collection/collection.dart';
part 'with_enum.g.dart';
part 'with_enum.serializer.g.dart';
@Serializable(autoIdAndDateFields: false)
abstract class _WithEnum {
WithEnumType get type;
List<int> get finalList;
Uint8List get imageBytes;
}
enum WithEnumType { a, b, c }

View file

@ -8,7 +8,7 @@ part of 'with_enum.dart';
@generatedSerializable
class WithEnum implements _WithEnum {
const WithEnum({this.type, List<int> this.finalList});
const WithEnum({this.type, List<int> this.finalList, this.imageBytes});
@override
final WithEnumType type;
@ -16,24 +16,85 @@ class WithEnum implements _WithEnum {
@override
final List<int> finalList;
WithEnum copyWith({WithEnumType type, List<int> finalList}) {
@override
final Uint8List imageBytes;
WithEnum copyWith(
{WithEnumType type, List<int> finalList, Uint8List imageBytes}) {
return new WithEnum(
type: type ?? this.type, finalList: finalList ?? this.finalList);
type: type ?? this.type,
finalList: finalList ?? this.finalList,
imageBytes: imageBytes ?? this.imageBytes);
}
bool operator ==(other) {
return other is _WithEnum &&
other.type == type &&
const ListEquality<int>(const DefaultEquality<int>())
.equals(other.finalList, finalList);
.equals(other.finalList, finalList) &&
const ListEquality().equals(other.imageBytes, imageBytes);
}
@override
int get hashCode {
return hashObjects([type, finalList]);
return hashObjects([type, finalList, imageBytes]);
}
Map<String, dynamic> toJson() {
return WithEnumSerializer.toMap(this);
}
}
// **************************************************************************
// SerializerGenerator
// **************************************************************************
abstract class WithEnumSerializer {
static WithEnum fromMap(Map map) {
return new WithEnum(
type: map['type'] is WithEnumType
? (map['type'] as WithEnumType)
: (map['type'] is int
? WithEnumType.values[map['type'] as int]
: null),
finalList: map['final_list'] is Iterable
? (map['final_list'] as Iterable).cast<int>().toList()
: null,
imageBytes: map['image_bytes'] is Uint8List
? (map['image_bytes'] as Uint8List)
: (map['image_bytes'] is Iterable<int>
? new Uint8List.fromList(
(map['image_bytes'] as Iterable<int>).toList())
: (map['image_bytes'] is String
? new Uint8List.fromList(
base64.decode(map['image_bytes'] as String))
: null)));
}
static Map<String, dynamic> toMap(WithEnum model) {
if (model == null) {
return null;
}
return {
'type':
model.type == null ? null : WithEnumType.values.indexOf(model.type),
'final_list': model.finalList,
'image_bytes':
model.imageBytes == null ? null : base64.encode(model.imageBytes)
};
}
}
abstract class WithEnumFields {
static const List<String> allFields = const <String>[
type,
finalList,
imageBytes
];
static const String type = 'type';
static const String finalList = 'final_list';
static const String imageBytes = 'image_bytes';
}

View file

@ -1,38 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'with_enum.dart';
// **************************************************************************
// SerializerGenerator
// **************************************************************************
abstract class WithEnumSerializer {
static WithEnum fromMap(Map map) {
return new WithEnum(
type: map['type'] is WithEnumType
? (map['type'] as WithEnumType)
: (map['type'] is int
? WithEnumType.values[map['type'] as int]
: null),
finalList: map['final_list'] as List<int>);
}
static Map<String, dynamic> toMap(WithEnum model) {
if (model == null) {
return null;
}
return {
'type':
model.type == null ? null : WithEnumType.values.indexOf(model.type),
'final_list': model.finalList
};
}
}
abstract class WithEnumFields {
static const List<String> allFields = const <String>[type, finalList];
static const String type = 'type';
static const String finalList = 'final_list';
}