Issue regarding Maps with null fields a generic custom mapper on third party class
Closed this issue · 2 comments
Thanks you for this great package. It has been a delight to use.
When creating a generic custom mapper for the Option type from fpdart
everything works well for toMap
and fromMap
when the field is not null
. However, when the field of the Map
is null
, I get the following error: MapperException: Failed to decode (ClassWithOption).optional: Parameter optional is missing.
Here is the custom mapper:
class OptionConverter extends SimpleMapper1<Option> {
const OptionConverter();
@override
Option<T> decode<T>(dynamic value) {
final content = MapperContainer.globals.fromValue<T>(value);
return content == null ? none<T>() : some<T>(content);
}
@override
dynamic encode<T>(Option<T> self) {
return MapperContainer.globals.toValue<T>(self.match(() => null, (t) => t));
}
@override
Function get typeFactory => <T>(f) => f<Option<T>>();
}
and here is a snippet of a class using the custom mapper:
@MappableClass(includeCustomMappers: [OptionConverter()])
class ClassWithOption with ClassWithOptionMappable {
ClassWithOption({
required this.optional,
required this.name,
});
final Option<String> optional;
final String name;
static const fromMap = ClassWithOptionMapper.fromMap;
}
It fails with the following snippet:
ClassWithOption.fromMap({'name': 'bob', 'optional': null})
I cannot tell if I am doing something wrong or if this is a bug.
Thanks again!
The reason this fails is because the null check (that triggers the MapperException you get) is done before invoking the mapper. This is because usually a mapper only works with non-null values. Option here is a special case.
I would propose a workaround to use a default value in the constructor like this:
class ClassWithOption with ClassWithOptionMappable {
ClassWithOption({
Option<String>? optional,
required this.name,
}) : optional = optional ?? none();
final Option<String> optional;
final String name;
static const fromMap = ClassWithOptionMapper.fromMap;
}
Thanks for the solution. It works as intended.