mirror of https://github.com/AMT-Cheif/drift.git
Implement new serialization api in generated classes
This commit is contained in:
parent
5db9a5f87d
commit
023c055e44
|
@ -22,17 +22,19 @@ class Category extends DataClass {
|
|||
.mapFromDatabaseResponse(data['${effectivePrefix}description']),
|
||||
);
|
||||
}
|
||||
factory Category.fromJson(Map<String, dynamic> json) {
|
||||
factory Category.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return Category(
|
||||
id: json['id'] as int,
|
||||
description: json['description'] as String,
|
||||
id: serializer.fromJson<int>(json['id']),
|
||||
description: serializer.fromJson<String>(json['description']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
Map<String, dynamic> toJson(
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return {
|
||||
'id': id,
|
||||
'description': description,
|
||||
'id': serializer.toJson<int>(id),
|
||||
'description': serializer.toJson<String>(description),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -140,21 +142,23 @@ class Recipe extends DataClass {
|
|||
intType.mapFromDatabaseResponse(data['${effectivePrefix}category']),
|
||||
);
|
||||
}
|
||||
factory Recipe.fromJson(Map<String, dynamic> json) {
|
||||
factory Recipe.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return Recipe(
|
||||
id: json['id'] as int,
|
||||
title: json['title'] as String,
|
||||
instructions: json['instructions'] as String,
|
||||
category: json['category'] as int,
|
||||
id: serializer.fromJson<int>(json['id']),
|
||||
title: serializer.fromJson<String>(json['title']),
|
||||
instructions: serializer.fromJson<String>(json['instructions']),
|
||||
category: serializer.fromJson<int>(json['category']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
Map<String, dynamic> toJson(
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return {
|
||||
'id': id,
|
||||
'title': title,
|
||||
'instructions': instructions,
|
||||
'category': category,
|
||||
'id': serializer.toJson<int>(id),
|
||||
'title': serializer.toJson<String>(title),
|
||||
'instructions': serializer.toJson<String>(instructions),
|
||||
'category': serializer.toJson<int>(category),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -295,19 +299,21 @@ class Ingredient extends DataClass {
|
|||
intType.mapFromDatabaseResponse(data['${effectivePrefix}calories']),
|
||||
);
|
||||
}
|
||||
factory Ingredient.fromJson(Map<String, dynamic> json) {
|
||||
factory Ingredient.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return Ingredient(
|
||||
id: json['id'] as int,
|
||||
name: json['name'] as String,
|
||||
caloriesPer100g: json['caloriesPer100g'] as int,
|
||||
id: serializer.fromJson<int>(json['id']),
|
||||
name: serializer.fromJson<String>(json['name']),
|
||||
caloriesPer100g: serializer.fromJson<int>(json['caloriesPer100g']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
Map<String, dynamic> toJson(
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return {
|
||||
'id': id,
|
||||
'name': name,
|
||||
'caloriesPer100g': caloriesPer100g,
|
||||
'id': serializer.toJson<int>(id),
|
||||
'name': serializer.toJson<String>(name),
|
||||
'caloriesPer100g': serializer.toJson<int>(caloriesPer100g),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -433,19 +439,21 @@ class IngredientInRecipe extends DataClass {
|
|||
intType.mapFromDatabaseResponse(data['${effectivePrefix}amount']),
|
||||
);
|
||||
}
|
||||
factory IngredientInRecipe.fromJson(Map<String, dynamic> json) {
|
||||
factory IngredientInRecipe.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return IngredientInRecipe(
|
||||
recipe: json['recipe'] as int,
|
||||
ingredient: json['ingredient'] as int,
|
||||
amountInGrams: json['amountInGrams'] as int,
|
||||
recipe: serializer.fromJson<int>(json['recipe']),
|
||||
ingredient: serializer.fromJson<int>(json['ingredient']),
|
||||
amountInGrams: serializer.fromJson<int>(json['amountInGrams']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
Map<String, dynamic> toJson(
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return {
|
||||
'recipe': recipe,
|
||||
'ingredient': ingredient,
|
||||
'amountInGrams': amountInGrams,
|
||||
'recipe': serializer.toJson<int>(recipe),
|
||||
'ingredient': serializer.toJson<int>(ingredient),
|
||||
'amountInGrams': serializer.toJson<int>(amountInGrams),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -5,13 +5,14 @@ import 'dart:convert';
|
|||
abstract class DataClass {
|
||||
const DataClass();
|
||||
|
||||
// todo better docs, explain ValueSerializer
|
||||
|
||||
/// Converts this object into a representation that can be encoded with
|
||||
/// [json].
|
||||
/// [json]. The [serializer] can be used to configure how individual values
|
||||
/// will be encoded.
|
||||
Map<String, dynamic> toJson(
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()});
|
||||
|
||||
/// Converts this object into a json representation. The [serializer] can be
|
||||
/// used to configure how individual values will be encoded.
|
||||
String toJsonString(
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return json.encode(toJson(serializer: serializer));
|
||||
|
@ -21,9 +22,17 @@ abstract class DataClass {
|
|||
/// Serializer responsible for mapping atomic types from and to json.
|
||||
abstract class ValueSerializer {
|
||||
const ValueSerializer();
|
||||
|
||||
/// The default serializer encodes date times as a unix-timestamp in
|
||||
/// milliseconds.
|
||||
const factory ValueSerializer.defaults() = _DefaultValueSerializer;
|
||||
|
||||
/// Converts the [value] to something that can be passed to
|
||||
/// [JsonCodec.encode].
|
||||
dynamic toJson<T>(T value);
|
||||
|
||||
/// Inverse of [toJson]: Converts a value obtained from [JsonCodec.decode]
|
||||
/// into a value that can be hold by data classes.
|
||||
T fromJson<T>(dynamic json);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,23 +33,25 @@ class TodoEntry extends DataClass {
|
|||
intType.mapFromDatabaseResponse(data['${effectivePrefix}category']),
|
||||
);
|
||||
}
|
||||
factory TodoEntry.fromJson(Map<String, dynamic> json) {
|
||||
factory TodoEntry.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return TodoEntry(
|
||||
id: json['id'] as int,
|
||||
title: json['title'] as String,
|
||||
content: json['content'] as String,
|
||||
targetDate: json['targetDate'] as DateTime,
|
||||
category: json['category'] as int,
|
||||
id: serializer.fromJson<int>(json['id']),
|
||||
title: serializer.fromJson<String>(json['title']),
|
||||
content: serializer.fromJson<String>(json['content']),
|
||||
targetDate: serializer.fromJson<DateTime>(json['targetDate']),
|
||||
category: serializer.fromJson<int>(json['category']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
Map<String, dynamic> toJson(
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return {
|
||||
'id': id,
|
||||
'title': title,
|
||||
'content': content,
|
||||
'targetDate': targetDate,
|
||||
'category': category,
|
||||
'id': serializer.toJson<int>(id),
|
||||
'title': serializer.toJson<String>(title),
|
||||
'content': serializer.toJson<String>(content),
|
||||
'targetDate': serializer.toJson<DateTime>(targetDate),
|
||||
'category': serializer.toJson<int>(category),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -215,17 +217,19 @@ class Category extends DataClass {
|
|||
stringType.mapFromDatabaseResponse(data['${effectivePrefix}desc']),
|
||||
);
|
||||
}
|
||||
factory Category.fromJson(Map<String, dynamic> json) {
|
||||
factory Category.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return Category(
|
||||
id: json['id'] as int,
|
||||
description: json['description'] as String,
|
||||
id: serializer.fromJson<int>(json['id']),
|
||||
description: serializer.fromJson<String>(json['description']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
Map<String, dynamic> toJson(
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return {
|
||||
'id': id,
|
||||
'description': description,
|
||||
'id': serializer.toJson<int>(id),
|
||||
'description': serializer.toJson<String>(description),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -340,23 +344,25 @@ class User extends DataClass {
|
|||
.mapFromDatabaseResponse(data['${effectivePrefix}creation_time']),
|
||||
);
|
||||
}
|
||||
factory User.fromJson(Map<String, dynamic> json) {
|
||||
factory User.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return User(
|
||||
id: json['id'] as int,
|
||||
name: json['name'] as String,
|
||||
isAwesome: json['isAwesome'] as bool,
|
||||
profilePicture: json['profilePicture'] as Uint8List,
|
||||
creationTime: json['creationTime'] as DateTime,
|
||||
id: serializer.fromJson<int>(json['id']),
|
||||
name: serializer.fromJson<String>(json['name']),
|
||||
isAwesome: serializer.fromJson<bool>(json['isAwesome']),
|
||||
profilePicture: serializer.fromJson<Uint8List>(json['profilePicture']),
|
||||
creationTime: serializer.fromJson<DateTime>(json['creationTime']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
Map<String, dynamic> toJson(
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return {
|
||||
'id': id,
|
||||
'name': name,
|
||||
'isAwesome': isAwesome,
|
||||
'profilePicture': profilePicture,
|
||||
'creationTime': creationTime,
|
||||
'id': serializer.toJson<int>(id),
|
||||
'name': serializer.toJson<String>(name),
|
||||
'isAwesome': serializer.toJson<bool>(isAwesome),
|
||||
'profilePicture': serializer.toJson<Uint8List>(profilePicture),
|
||||
'creationTime': serializer.toJson<DateTime>(creationTime),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -515,17 +521,19 @@ class SharedTodo extends DataClass {
|
|||
user: intType.mapFromDatabaseResponse(data['${effectivePrefix}user']),
|
||||
);
|
||||
}
|
||||
factory SharedTodo.fromJson(Map<String, dynamic> json) {
|
||||
factory SharedTodo.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return SharedTodo(
|
||||
todo: json['todo'] as int,
|
||||
user: json['user'] as int,
|
||||
todo: serializer.fromJson<int>(json['todo']),
|
||||
user: serializer.fromJson<int>(json['user']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
Map<String, dynamic> toJson(
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return {
|
||||
'todo': todo,
|
||||
'user': user,
|
||||
'todo': serializer.toJson<int>(todo),
|
||||
'user': serializer.toJson<int>(user),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -632,17 +640,19 @@ class TableWithoutPKData extends DataClass {
|
|||
numType.mapFromDatabaseResponse(data['${effectivePrefix}some_float']),
|
||||
);
|
||||
}
|
||||
factory TableWithoutPKData.fromJson(Map<String, dynamic> json) {
|
||||
factory TableWithoutPKData.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return TableWithoutPKData(
|
||||
notReallyAnId: json['notReallyAnId'] as int,
|
||||
someFloat: json['someFloat'] as num,
|
||||
notReallyAnId: serializer.fromJson<int>(json['notReallyAnId']),
|
||||
someFloat: serializer.fromJson<num>(json['someFloat']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
Map<String, dynamic> toJson(
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return {
|
||||
'notReallyAnId': notReallyAnId,
|
||||
'someFloat': someFloat,
|
||||
'notReallyAnId': serializer.toJson<int>(notReallyAnId),
|
||||
'someFloat': serializer.toJson<num>(someFloat),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -8,27 +8,17 @@ import 'package:path/path.dart';
|
|||
|
||||
import 'format_coverage.dart' as fc;
|
||||
|
||||
const int _vmPort = 9876;
|
||||
|
||||
Future<void> main(List<String> args) async {
|
||||
// First, generate the build script, see
|
||||
// https://github.com/dart-lang/build/blob/3208cfe94c475ed3e1ec44c227aadaddaeac263d/build_runner/bin/build_runner.dart#L65
|
||||
Pub.run('build_runner', arguments: ['generate-build-script']);
|
||||
|
||||
// Start coverage collection (resume isolates, don't wait for pause, collect
|
||||
// when isolates exit).
|
||||
final collectorFuture =
|
||||
collect(Uri.parse('http://localhost:$_vmPort'), true, false, true);
|
||||
|
||||
// Next, run the test script in another dart process that has the vm services
|
||||
// enabled.
|
||||
final tests = join(File.fromUri(Platform.script).parent.path, 'tester.dart');
|
||||
// not using Dart.run because that only prints to stdout after the process has
|
||||
// completed.
|
||||
await Dart.runAsync(tests,
|
||||
vmArgs: ['--enable-vm-service=$_vmPort', '--pause-isolates-on-exit']);
|
||||
final coverage = await runAndCollect(tests, onExit: true, printOutput: true);
|
||||
|
||||
File('coverage.json').writeAsStringSync(json.encode(await collectorFuture));
|
||||
File('coverage.json').writeAsStringSync(json.encode(coverage));
|
||||
|
||||
print('formatting to .lcov format');
|
||||
await fc.main();
|
||||
|
|
|
@ -101,25 +101,34 @@ class DataClassWriter {
|
|||
final dataClassName = table.dartTypeName;
|
||||
|
||||
buffer
|
||||
..write('factory $dataClassName.fromJson(Map<String, dynamic> json) {\n')
|
||||
..write('factory $dataClassName.fromJson('
|
||||
'Map<String, dynamic> json,'
|
||||
'{ValueSerializer serializer = const ValueSerializer.defaults()}'
|
||||
') {\n')
|
||||
..write('return $dataClassName(');
|
||||
|
||||
for (var column in table.columns) {
|
||||
final getter = column.dartGetterName;
|
||||
final type = column.dartTypeName;
|
||||
|
||||
buffer.write("$getter: json['$getter'] as $type,");
|
||||
buffer.write("$getter: serializer.fromJson<$type>(json['$getter']),");
|
||||
}
|
||||
|
||||
buffer.write(');}\n');
|
||||
}
|
||||
|
||||
void _writeToJson(StringBuffer buffer) {
|
||||
buffer.write('@override Map<String, dynamic> toJson() {\n return {');
|
||||
buffer.write('@override Map<String, dynamic> toJson('
|
||||
'{ValueSerializer serializer = const ValueSerializer.defaults()}) {'
|
||||
'\n return {');
|
||||
|
||||
for (var column in table.columns) {
|
||||
final getter = column.dartGetterName;
|
||||
buffer.write("'$getter': $getter,");
|
||||
final name = column.dartGetterName;
|
||||
final needsThis = name == 'serializer';
|
||||
final value = needsThis ? 'this.$name' : name;
|
||||
|
||||
buffer
|
||||
.write("'$name': serializer.toJson<${column.dartTypeName}>($value),");
|
||||
}
|
||||
|
||||
buffer.write('};}');
|
||||
|
|
Loading…
Reference in New Issue