Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Field's name reverse mapping #157

Merged
merged 3 commits into from
Nov 26, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 27 additions & 3 deletions packages/auto_mappr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ Heavily inspired by [C# AutoMapper][auto_mapper_net_link].
- [Mapping from source](#mapping-from-source)
- [Nullability handling](#nullability-handling)
- [Forced non-nullable field for nullable source](#forced-non-nullable-field-for-nullable-source)
- [Type converters](#type-converters)
- [Generics](#generics)
- [Library import aliases](#library-import-aliases)
- [Modules](#modules)
- [Including](#including)
- [Delegating](#delegating)
- [Delegating](#delegating)
- [Type converters](#type-converters)
- [Reverse mapping](#reverse-mapping)
- [Records](#records)
- [Works with `equatable`](#works-with-equatable)
Expand Down Expand Up @@ -748,8 +748,32 @@ you can use `reverse` option on `MapType`.
Note that it's your responsibility to make sure those objects
support normal and reverse mapping
and to keep them in sync.

When `Field`'s mapping with `from` parameter is used, in `reverse` mapping those properties are automatically switched too.

For example

```dart
class A {
final String a;
}

class B {
final String b;
}

// Mapping
MapType<A,B>(fields: [
Field('b', from: 'a')
], reverse: true)

// generated mapping
A.a mapts to B.b
B.b maps to A.a
```

Also note that reverse mapping might not work properly when additional configuration
such as [whenSourceIsNull] or [constructor] is used.
such as `whenSourceIsNull` or `constructor` is used.

For more complicated scenarios two separate mappings are recommended instead.

Expand Down
16 changes: 15 additions & 1 deletion packages/auto_mappr/lib/src/generator/auto_mappr_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,21 @@ class AutoMapprGenerator extends GeneratorForAnnotation<annotation.AutoMappr> {
TypeMapping(
source: targetType,
target: sourceType,
fieldMappings: fieldMappings ?? [],
fieldMappings: fieldMappings
?.map(
(f) => f.from != null
? FieldMapping(
field: f.from!,
from: f.field,
customExpression: f.customExpression,
whenNullExpression: f.whenNullExpression,
ignore: f.ignore,
ignoreNull: f.ignoreNull,
)
: f,
)
.toList() ??
[],
typeConverters: [..._toTypeConverters(mapTypeConverters), ...globalConverters],
whenSourceIsNullExpression: whenSourceIsNull,
constructor: constructor,
Expand Down
17 changes: 17 additions & 0 deletions packages/auto_mappr/test/integration/fixture/reverse.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ import 'reverse.auto_mappr.dart';
MapType<PrimitiveDto, Primitive>(reverse: true),
MapType<UserDto, User>(reverse: true),
MapType<AddressDto, Address>(reverse: true),
MapType<AddressDto, SpecialAddress>(
fields: [
Field('specialStreet', from: 'street'),
Field('specialCity', from: 'city'),
],
reverse: true,
),
])
class Mappr extends $Mappr {
const Mappr();
Expand Down Expand Up @@ -77,3 +84,13 @@ class AddressDto extends Equatable {

const AddressDto({required this.street, required this.city});
}

class SpecialAddress extends Equatable {
final String specialStreet;
final String specialCity;

@override
List<Object?> get props => [specialStreet, specialCity];

const SpecialAddress({required this.specialStreet, required this.specialCity});
}
18 changes: 18 additions & 0 deletions packages/auto_mappr/test/integration/reverse_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,22 @@ void main() {
);
});
});

group('Reverse mapping with custom fields', () {
test('AddressDto to SpecialAddress', () {
const dto = fixture.AddressDto(street: 'Street 14', city: 'Wakanda');

final converted = mappr.convert<fixture.AddressDto, fixture.SpecialAddress>(dto);

expect(converted, equals(const fixture.SpecialAddress(specialStreet: 'Street 14', specialCity: 'Wakanda')));
});

test('SpecialAddress to AddressDto', () {
const dto = fixture.SpecialAddress(specialStreet: 'Street 14', specialCity: 'Wakanda');

final converted = mappr.convert<fixture.SpecialAddress, fixture.AddressDto>(dto);

expect(converted, equals(const fixture.AddressDto(street: 'Street 14', city: 'Wakanda')));
});
});
}