automap 0.1.0
automap: ^0.1.0 copied to clipboard
A lightweight object mapper for Dart, with support for automatic JSON-based mapping and manual mapping expressions.
automap #
A lightweight object mapper for Dart. It maps objects of different classes automatically, through JSON serialization, or manually, through custom mapping expressions.
Installation #
Add it to your pubspec.yaml:
dependencies:
automap: ^0.1.0
Usage #
Auto map #
Implement AutoMapperModel on the source type and register an expression
that builds the target from the serialized source:
import 'package:automap/automap.dart';
class AutoSource implements AutoMapperModel {
const AutoSource(this.x);
final int x;
@override
Map<String, dynamic> toAutoJson() => {'x': x};
}
class AutoTarget {
const AutoTarget(this.x);
final int x;
static AutoTarget fromAutoJson(Map<String, dynamic> json) =>
AutoTarget(json['x'] as int);
}
void main() {
AutoMapper.I.addAutoMap<AutoSource, AutoTarget>(AutoTarget.fromAutoJson);
final target = AutoMapper.I.map<AutoSource, AutoTarget>(const AutoSource(5));
print(target.x); // 5
}
Manual map #
For full control, register a manual map expression:
class ManualSource {
const ManualSource(this.x);
final int x;
}
class ManualTarget {
const ManualTarget(this.x);
final int x;
}
void main() {
AutoMapper.I.addManualMap<ManualSource, ManualTarget>(
(source, mapper, params) => ManualTarget(source.x),
);
final target = AutoMapper.I.map<ManualSource, ManualTarget>(
const ManualSource(5),
);
print(target.x); // 5
}
Mapping parameters #
Manual map expressions receive an optional params map:
AutoMapper.I.addManualMap<Person, PersonDto>(
(source, mapper, params) => PersonDto(
'${source.name} ${params['suffix']}',
source.age + (params['bonus'] as int),
),
);
final dto = AutoMapper.I.map<Person, PersonDto>(
const Person('Ada', 36),
{'suffix': 'Lovelace', 'bonus': 1},
);
Nested mapping #
The expression also receives the calling [AutoMapper] instance, so child members can be mapped with registered maps:
AutoMapper.I
..addAutoMap<Person, PersonDto>(PersonDto.fromAutoJson)
..addManualMap<Team, TeamDto>(
(source, mapper, params) =>
TeamDto(mapper.map<Person, PersonDto>(source.leader)),
);
final teamDto = AutoMapper.I.map<Team, TeamDto>(const Team(Person('Ada', 36)));
Error handling #
Every exception thrown by this package extends the sealed
AutoMapperException class, so you can handle all failure modes exhaustively
with pattern matching:
try {
final dto = AutoMapper.I.map<Person, PersonDto>(person);
} on AutoMapperException catch (e) {
switch (e) {
case MapException(:final cause, :final stackTrace):
print('The mapping expression failed: $cause');
case MapDoesNotExistException(:final source, :final destination):
print('No map registered for $source -> $destination');
case MapDuplicateException(:final source, :final destination):
print('A map for $source -> $destination already exists');
}
}
Note that exceptions thrown inside your own mapping expressions are wrapped
in a MapException that keeps the original cause and stack trace, while
programming errors (Error instances, such as type errors) propagate
untouched so bugs are never masked.
Limitations #
This package does not use reflection or code generation. Automatic mapping
works through the AutoMapperModel contract (toAutoJson plus a
constructor-like expression), so mapping always goes through an intermediate
JSON-like map.