Api to globally override the default ValueSerializer

Closes #303
This commit is contained in:
Simon Binder 2019-12-27 18:17:45 +01:00
parent 927fbf561b
commit e9cada5e54
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
8 changed files with 140 additions and 75 deletions

View File

@ -2,6 +2,12 @@
- New `clientDefault` method for columns. It can be used for dynamic defaults that might be different for
each row. For instance, you can generate a uuid for each row with `text().clientDefault(() => Uuid().v4()();`
- Ability to override the default `ValueSerializer` globally by using `moorRuntimeOptions.valueSerializer`.
- Moor files: You can now explicitly declare column types in those cases that the analyzer can't
infer it:
```
selectVariable(:variable AS TEXT): SELECT :variable;
```
## 2.2.0

View File

@ -23,20 +23,21 @@ class Category extends DataClass implements Insertable<Category> {
);
}
factory Category.fromJson(Map<String, dynamic> json,
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
{ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return Category(
id: serializer.fromJson<int>(json['id']),
description: serializer.fromJson<String>(json['description']),
);
}
factory Category.fromJsonString(String encodedJson,
{ValueSerializer serializer = const ValueSerializer.defaults()}) =>
{ValueSerializer serializer}) =>
Category.fromJson(
DataClass.parseJson(encodedJson) as Map<String, dynamic>,
serializer: serializer);
@override
Map<String, dynamic> toJson(
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
Map<String, dynamic> toJson({ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'id': serializer.toJson<int>(id),
'description': serializer.toJson<String>(description),
@ -197,7 +198,8 @@ class Recipe extends DataClass implements Insertable<Recipe> {
);
}
factory Recipe.fromJson(Map<String, dynamic> json,
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
{ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return Recipe(
id: serializer.fromJson<int>(json['id']),
title: serializer.fromJson<String>(json['title']),
@ -206,12 +208,12 @@ class Recipe extends DataClass implements Insertable<Recipe> {
);
}
factory Recipe.fromJsonString(String encodedJson,
{ValueSerializer serializer = const ValueSerializer.defaults()}) =>
{ValueSerializer serializer}) =>
Recipe.fromJson(DataClass.parseJson(encodedJson) as Map<String, dynamic>,
serializer: serializer);
@override
Map<String, dynamic> toJson(
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
Map<String, dynamic> toJson({ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'id': serializer.toJson<int>(id),
'title': serializer.toJson<String>(title),
@ -432,7 +434,8 @@ class Ingredient extends DataClass implements Insertable<Ingredient> {
);
}
factory Ingredient.fromJson(Map<String, dynamic> json,
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
{ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return Ingredient(
id: serializer.fromJson<int>(json['id']),
name: serializer.fromJson<String>(json['name']),
@ -440,13 +443,13 @@ class Ingredient extends DataClass implements Insertable<Ingredient> {
);
}
factory Ingredient.fromJsonString(String encodedJson,
{ValueSerializer serializer = const ValueSerializer.defaults()}) =>
{ValueSerializer serializer}) =>
Ingredient.fromJson(
DataClass.parseJson(encodedJson) as Map<String, dynamic>,
serializer: serializer);
@override
Map<String, dynamic> toJson(
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
Map<String, dynamic> toJson({ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'id': serializer.toJson<int>(id),
'name': serializer.toJson<String>(name),
@ -641,7 +644,8 @@ class IngredientInRecipe extends DataClass
);
}
factory IngredientInRecipe.fromJson(Map<String, dynamic> json,
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
{ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return IngredientInRecipe(
recipe: serializer.fromJson<int>(json['recipe']),
ingredient: serializer.fromJson<int>(json['ingredient']),
@ -649,13 +653,13 @@ class IngredientInRecipe extends DataClass
);
}
factory IngredientInRecipe.fromJsonString(String encodedJson,
{ValueSerializer serializer = const ValueSerializer.defaults()}) =>
{ValueSerializer serializer}) =>
IngredientInRecipe.fromJson(
DataClass.parseJson(encodedJson) as Map<String, dynamic>,
serializer: serializer);
@override
Map<String, dynamic> toJson(
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
Map<String, dynamic> toJson({ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'recipe': serializer.toJson<int>(recipe),
'ingredient': serializer.toJson<int>(ingredient),

View File

@ -15,6 +15,9 @@ part 'query_engine.dart';
class MoorRuntimeOptions {
/// Don't warn when a database class isn't used as singleton.
bool dontWarnAboutMultipleDatabases = false;
/// The [ValueSerializer] that will be used by default in [DataClass.toJson].
ValueSerializer defaultSerializer = const ValueSerializer.defaults();
}
/// Stores the [MoorRuntimeOptions] describing global moor behavior across

View File

@ -24,14 +24,15 @@ abstract class DataClass {
/// Converts this object into a representation that can be encoded with
/// [json]. The [serializer] can be used to configure how individual values
/// will be encoded.
Map<String, dynamic> toJson(
{ValueSerializer serializer = const ValueSerializer.defaults()});
/// will be encoded. By default, [MoorRuntimeOptions.defaultSerializer] will
/// be used. See [ValueSerializer.defaults()] for details.
Map<String, dynamic> toJson({ValueSerializer serializer});
/// 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()}) {
/// used to configure how individual values will be encoded. By default,
/// [MoorRuntimeOptions.defaultSerializer] will be used. See
/// [ValueSerializer.defaults()] for details.
String toJsonString({ValueSerializer serializer}) {
return json.encode(toJson(serializer: serializer));
}

View File

@ -20,18 +20,19 @@ class NoId extends DataClass implements Insertable<NoId> {
);
}
factory NoId.fromJson(Map<String, dynamic> json,
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
{ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return NoId(
payload: serializer.fromJson<Uint8List>(json['payload']),
);
}
factory NoId.fromJsonString(String encodedJson,
{ValueSerializer serializer = const ValueSerializer.defaults()}) =>
{ValueSerializer serializer}) =>
NoId.fromJson(DataClass.parseJson(encodedJson) as Map<String, dynamic>,
serializer: serializer);
@override
Map<String, dynamic> toJson(
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
Map<String, dynamic> toJson({ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'payload': serializer.toJson<Uint8List>(payload),
};
@ -154,20 +155,21 @@ class WithDefault extends DataClass implements Insertable<WithDefault> {
);
}
factory WithDefault.fromJson(Map<String, dynamic> json,
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
{ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return WithDefault(
a: serializer.fromJson<String>(json['a']),
b: serializer.fromJson<int>(json['b']),
);
}
factory WithDefault.fromJsonString(String encodedJson,
{ValueSerializer serializer = const ValueSerializer.defaults()}) =>
{ValueSerializer serializer}) =>
WithDefault.fromJson(
DataClass.parseJson(encodedJson) as Map<String, dynamic>,
serializer: serializer);
@override
Map<String, dynamic> toJson(
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
Map<String, dynamic> toJson({ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'a': serializer.toJson<String>(a),
'b': serializer.toJson<int>(b),
@ -313,7 +315,8 @@ class WithConstraint extends DataClass implements Insertable<WithConstraint> {
);
}
factory WithConstraint.fromJson(Map<String, dynamic> json,
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
{ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return WithConstraint(
a: serializer.fromJson<String>(json['a']),
b: serializer.fromJson<int>(json['b']),
@ -321,13 +324,13 @@ class WithConstraint extends DataClass implements Insertable<WithConstraint> {
);
}
factory WithConstraint.fromJsonString(String encodedJson,
{ValueSerializer serializer = const ValueSerializer.defaults()}) =>
{ValueSerializer serializer}) =>
WithConstraint.fromJson(
DataClass.parseJson(encodedJson) as Map<String, dynamic>,
serializer: serializer);
@override
Map<String, dynamic> toJson(
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
Map<String, dynamic> toJson({ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'a': serializer.toJson<String>(a),
'b': serializer.toJson<int>(b),
@ -498,19 +501,20 @@ class Config extends DataClass implements Insertable<Config> {
);
}
factory Config.fromJson(Map<String, dynamic> json,
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
{ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return Config(
configKey: serializer.fromJson<String>(json['config_key']),
configValue: serializer.fromJson<String>(json['config_value']),
);
}
factory Config.fromJsonString(String encodedJson,
{ValueSerializer serializer = const ValueSerializer.defaults()}) =>
{ValueSerializer serializer}) =>
Config.fromJson(DataClass.parseJson(encodedJson) as Map<String, dynamic>,
serializer: serializer);
@override
Map<String, dynamic> toJson(
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
Map<String, dynamic> toJson({ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'config_key': serializer.toJson<String>(configKey),
'config_value': serializer.toJson<String>(configValue),
@ -673,7 +677,8 @@ class MytableData extends DataClass implements Insertable<MytableData> {
);
}
factory MytableData.fromJson(Map<String, dynamic> json,
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
{ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return MytableData(
someid: serializer.fromJson<int>(json['someid']),
sometext: serializer.fromJson<String>(json['sometext']),
@ -682,13 +687,13 @@ class MytableData extends DataClass implements Insertable<MytableData> {
);
}
factory MytableData.fromJsonString(String encodedJson,
{ValueSerializer serializer = const ValueSerializer.defaults()}) =>
{ValueSerializer serializer}) =>
MytableData.fromJson(
DataClass.parseJson(encodedJson) as Map<String, dynamic>,
serializer: serializer);
@override
Map<String, dynamic> toJson(
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
Map<String, dynamic> toJson({ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'someid': serializer.toJson<int>(someid),
'sometext': serializer.toJson<String>(sometext),
@ -897,7 +902,8 @@ class EMail extends DataClass implements Insertable<EMail> {
);
}
factory EMail.fromJson(Map<String, dynamic> json,
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
{ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return EMail(
sender: serializer.fromJson<String>(json['sender']),
title: serializer.fromJson<String>(json['title']),
@ -905,12 +911,12 @@ class EMail extends DataClass implements Insertable<EMail> {
);
}
factory EMail.fromJsonString(String encodedJson,
{ValueSerializer serializer = const ValueSerializer.defaults()}) =>
{ValueSerializer serializer}) =>
EMail.fromJson(DataClass.parseJson(encodedJson) as Map<String, dynamic>,
serializer: serializer);
@override
Map<String, dynamic> toJson(
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
Map<String, dynamic> toJson({ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'sender': serializer.toJson<String>(sender),
'title': serializer.toJson<String>(title),

View File

@ -38,7 +38,8 @@ class TodoEntry extends DataClass implements Insertable<TodoEntry> {
);
}
factory TodoEntry.fromJson(Map<String, dynamic> json,
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
{ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return TodoEntry(
id: serializer.fromJson<int>(json['id']),
title: serializer.fromJson<String>(json['title']),
@ -48,13 +49,13 @@ class TodoEntry extends DataClass implements Insertable<TodoEntry> {
);
}
factory TodoEntry.fromJsonString(String encodedJson,
{ValueSerializer serializer = const ValueSerializer.defaults()}) =>
{ValueSerializer serializer}) =>
TodoEntry.fromJson(
DataClass.parseJson(encodedJson) as Map<String, dynamic>,
serializer: serializer);
@override
Map<String, dynamic> toJson(
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
Map<String, dynamic> toJson({ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'id': serializer.toJson<int>(id),
'title': serializer.toJson<String>(title),
@ -309,20 +310,21 @@ class Category extends DataClass implements Insertable<Category> {
);
}
factory Category.fromJson(Map<String, dynamic> json,
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
{ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return Category(
id: serializer.fromJson<int>(json['id']),
description: serializer.fromJson<String>(json['description']),
);
}
factory Category.fromJsonString(String encodedJson,
{ValueSerializer serializer = const ValueSerializer.defaults()}) =>
{ValueSerializer serializer}) =>
Category.fromJson(
DataClass.parseJson(encodedJson) as Map<String, dynamic>,
serializer: serializer);
@override
Map<String, dynamic> toJson(
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
Map<String, dynamic> toJson({ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'id': serializer.toJson<int>(id),
'description': serializer.toJson<String>(description),
@ -488,7 +490,8 @@ class User extends DataClass implements Insertable<User> {
);
}
factory User.fromJson(Map<String, dynamic> json,
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
{ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return User(
id: serializer.fromJson<int>(json['id']),
name: serializer.fromJson<String>(json['name']),
@ -498,12 +501,12 @@ class User extends DataClass implements Insertable<User> {
);
}
factory User.fromJsonString(String encodedJson,
{ValueSerializer serializer = const ValueSerializer.defaults()}) =>
{ValueSerializer serializer}) =>
User.fromJson(DataClass.parseJson(encodedJson) as Map<String, dynamic>,
serializer: serializer);
@override
Map<String, dynamic> toJson(
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
Map<String, dynamic> toJson({ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'id': serializer.toJson<int>(id),
'name': serializer.toJson<String>(name),
@ -760,20 +763,21 @@ class SharedTodo extends DataClass implements Insertable<SharedTodo> {
);
}
factory SharedTodo.fromJson(Map<String, dynamic> json,
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
{ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return SharedTodo(
todo: serializer.fromJson<int>(json['todo']),
user: serializer.fromJson<int>(json['user']),
);
}
factory SharedTodo.fromJsonString(String encodedJson,
{ValueSerializer serializer = const ValueSerializer.defaults()}) =>
{ValueSerializer serializer}) =>
SharedTodo.fromJson(
DataClass.parseJson(encodedJson) as Map<String, dynamic>,
serializer: serializer);
@override
Map<String, dynamic> toJson(
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
Map<String, dynamic> toJson({ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'todo': serializer.toJson<int>(todo),
'user': serializer.toJson<int>(user),
@ -939,7 +943,8 @@ class TableWithoutPKData extends DataClass
);
}
factory TableWithoutPKData.fromJson(Map<String, dynamic> json,
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
{ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return TableWithoutPKData(
notReallyAnId: serializer.fromJson<int>(json['notReallyAnId']),
someFloat: serializer.fromJson<double>(json['someFloat']),
@ -947,13 +952,13 @@ class TableWithoutPKData extends DataClass
);
}
factory TableWithoutPKData.fromJsonString(String encodedJson,
{ValueSerializer serializer = const ValueSerializer.defaults()}) =>
{ValueSerializer serializer}) =>
TableWithoutPKData.fromJson(
DataClass.parseJson(encodedJson) as Map<String, dynamic>,
serializer: serializer);
@override
Map<String, dynamic> toJson(
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
Map<String, dynamic> toJson({ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'notReallyAnId': serializer.toJson<int>(notReallyAnId),
'someFloat': serializer.toJson<double>(someFloat),
@ -1152,20 +1157,21 @@ class PureDefault extends DataClass implements Insertable<PureDefault> {
);
}
factory PureDefault.fromJson(Map<String, dynamic> json,
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
{ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return PureDefault(
id: serializer.fromJson<int>(json['id']),
txt: serializer.fromJson<String>(json['txt']),
);
}
factory PureDefault.fromJsonString(String encodedJson,
{ValueSerializer serializer = const ValueSerializer.defaults()}) =>
{ValueSerializer serializer}) =>
PureDefault.fromJson(
DataClass.parseJson(encodedJson) as Map<String, dynamic>,
serializer: serializer);
@override
Map<String, dynamic> toJson(
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
Map<String, dynamic> toJson({ValueSerializer serializer}) {
serializer ??= moorRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'id': serializer.toJson<int>(id),
'txt': serializer.toJson<String>(txt),

View File

@ -1,3 +1,4 @@
import 'package:moor/moor.dart';
import 'package:test/test.dart';
import 'data/tables/todos.dart';
@ -16,4 +17,41 @@ void main() {
expect(deserialized, equals(deserialized));
});
test('default serializer can be overridden globally', () {
final old = moorRuntimeOptions.defaultSerializer;
moorRuntimeOptions.defaultSerializer = _MySerializer();
final entry = TodoEntry(
id: 13,
title: 'Title',
content: 'Content',
category: 3,
targetDate: DateTime.now(),
);
expect(
entry.toJson(),
{
'id': 'foo',
'title': 'foo',
'content': 'foo',
'category': 'foo',
'target_date': 'foo',
},
);
moorRuntimeOptions.defaultSerializer = old;
});
}
class _MySerializer extends ValueSerializer {
@override
T fromJson<T>(dynamic json) {
throw StateError('Should not be called');
}
@override
dynamic toJson<T>(T value) {
return 'foo';
}
}

View File

@ -108,9 +108,9 @@ class DataClassWriter {
_buffer
..write('factory $dataClassName.fromJson('
'Map<String, dynamic> json,'
'{ValueSerializer serializer = const ValueSerializer.defaults()}'
'Map<String, dynamic> json, {ValueSerializer serializer}'
') {\n')
..write('serializer ??= moorRuntimeOptions.defaultSerializer;\n')
..write('return $dataClassName(');
for (final column in table.columns) {
@ -126,7 +126,7 @@ class DataClassWriter {
if (scope.writer.options.generateFromJsonStringConstructor) {
// also generate a constructor that only takes a json string
_buffer.write('factory $dataClassName.fromJsonString(String encodedJson, '
'{ValueSerializer serializer = const ValueSerializer.defaults()}) => '
'{ValueSerializer serializer}) => '
'$dataClassName.fromJson('
'DataClass.parseJson(encodedJson) as Map<String, dynamic>, '
'serializer: serializer);');
@ -135,8 +135,9 @@ class DataClassWriter {
void _writeToJson() {
_buffer.write('@override Map<String, dynamic> toJson('
'{ValueSerializer serializer = const ValueSerializer.defaults()}) {'
'\n return <String, dynamic>{');
'{ValueSerializer serializer}) {\n'
'serializer ??= moorRuntimeOptions.defaultSerializer;\n'
'return <String, dynamic>{\n');
for (final column in table.columns) {
final name = column.getJsonKey(scope.options);