NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
pub.dev · #1276 most downloaded on pub.dev
Improved json serialization and data classes with full support for generics, inheritance, customization and more.
Last release 1 months ago
07 Sep 2026
Ships fairly regularly
a new release about every 6 weeks
Nearly every release is documented
notes for 42 of 46 stable releases
Nothing withdrawn
no release was ever pulled
5 years old
68 releases · first in 2022
Add support for Primary Constructors.
Allow analyzer to >=13.0.0 <15.0.0
analyzer to >=13.0.0 <15.0.0One column per quarter.
Bump analyzer to >=13.0.0 <14.0.0
analyzer to >=13.0.0 <14.0.0Bump analyzer to >=10.0.0 <13.0.0.
analyzer to >=10.0.0 <13.0.0.analyzer 10.0.0.useNodoc option for excluding generated classes from dartdoc output.copyWith parameters in some cases.Nothing published for this version
Fix nested copyWith on a inherited class with the superclass and field type in another library.
copyWith on a inherited class with the superclass and field type in another library.invalid_use_of_protected_member warning in generated code.Added support for annotated enum typedefs.
- Allow analyzer 9.0.0.
analyzer 9.0.0.Record mappers now correctly uses hooks specified on the @MappableRecord annotation.
@MappableRecord annotation.initializeMappers() method.analyzerto ^8.0.0, and build and source_gen to ^4.0.0.Migrate to new element2 analyzer model. Bump analyzer to >=7.5.9, build to 3.0.0 and source_gen to 3.0.0.
element2 analyzer model.
Bump analyzer to >=7.5.9, build to 3.0.0 and source_gen to 3.0.0.T extends Comparable<T>)// dart format off.sdk: >=3.7.0.Added support for shallowEncoding and includeTypeId options of @MappableClass().
shallowEncoding and includeTypeId options of @MappableClass().Update analyzer to >=7.0.0 <8.0.0 and source_gen to ^2.0.0. Bump other dependencies accordingly.
analyzer to >=7.0.0 <8.0.0 and source_gen to ^2.0.0. Bump other dependencies accordingly.sdk: >=3.6.0.Nothing published for this version
Fixed bug with bounded generic deep copyWith parameters.
Added support for reusing annotations as constant variables.
Added lint ignores for 'override_on_non_overriding_member'.
Fixed issues with adding unnecessary '__type' property for nullable generics.
- Performance improvements.
Deprecated creating and linking custom MapperContainers. If you are affected by this see https://github.com/schultek/dart_mappable/issues/159.
MapperContainers.
If you are affected by this see https://github.com/schultek/dart_mappable/issues/159.Added support for shallow encoding a class:
MyClassMapper.ensureInitialized().encodeMap<MyClass>(myClass, EncodingOptions(shallow: true))$ in class names.IterableMapper.equalityMode = IterableEqualityMode.unorderedbuild_extensions option to builder configuration.Added support for generic typed parameters for deep copyWith.
Fields of a class can now be any record type.
Require sdk: >=3.0.0.
Added support for Records.
Fields of a class can now be any record type.
You can annotate toplevel record typedefs:
@MappableRecord()
typedef Coordinates = ({double latitude, double longitude});dart_mappable supports record fields out of the box.
When you define a class, any field using a record type will be automatically included in the serialization.
@MappableClass()
class Location with LocationMappable {
const Location({
required this.name,
required this.coordinates,
});
final (String, String) name;
final ({double lat, double lng}) coordinates;
}An instance of this class would be encoded to:
{
"name": {
"$1": "John",
"$2": "Doe"
},
"coordinates": {
"lat": 123,
"lng": 456
}
}Additionally, you can create record type aliases using annotated typedefs:
@MappableRecord()
typedef Coordinates = ({double lat, double lng});When using this type for a field of another class, it will be serialized as expected.
This also allows you to serialize records using the standalone generated mapper class as well as the generated extension methods:
void main() {
// Using the generated mapper class.
Coordinates coords = CoordinatesMapper.fromJson('{"lat": 123, "lng": 456}');
// Using the generated extension methods.
String json = coords.toJson();
}You can also annotate individual fields of a record alias to change the key or add a hook:
@MappableRecord()
typedef FullName = (@MappableField(key: 'firstName') String, @MappableField(hook: MyHook()) String);This will only work on annotated record type aliases, not inline record fields.
Note: Since typedefs are just an alias for a type, you cannot define two aliases for the same type
with different @MappableField() modifiers. Only one will be used for serialization.
Require sdk: >=3.0.0.
Added support for Records.
Fields of a class can now be any record type.
You can annotate toplevel record typedefs:
@MappableRecord()
typedef Coordinates = ({double latitude, double longitude});
For a more detailed usage see the documentation.
Nothing published for this version
Nothing published for this version
Nothing published for this version
Make enum encoding explicitly typed.
Respect keys and hooks for annotated getters.
Handle even more cases for generic subclassing.
Handle bounded nested type parameters in subclasses.
Added support for annotating getters with @MappableField, which will then be included in the encoding, equality checks, and stringification of that cl
@MappableField, which will then be included in the encoding,
equality checks, and stringification of that class.Fixed bug with broken mapper generation.
The builder now respects basic initializer expressions of a constructor. This makes it possible to do field renaming or assigning to private fields wi
The builder now respects basic initializer expressions of a constructor. This makes it
possible to do field renaming or assigning to private fields without requiring an additional
getter matching the parameter.
The following is now supported out of the box:
class MyClass {
MyClass(int value, {String? name})
// Effectively renaming 'value' to 'data'.
: data = value,
// Assigning to a private field + having a null fallback.
_name = name ?? 'Unnamed';
final int value;
final String _name;Fixed encoding of a map now returns a Map<String, dynamic> where possible
(instead of a Map<dynamic, dynamic>)
Fixed supporting expressions in @MappableClass.includeCustomMappers.
Fixed error when using non-literal values in @MappableValue().
Fixed generic decoding when using generic superclass.
Fixed unknown-type bug for serialized non-constructor fields.
Fixed bug with undetermined includeSubClasses.
@MappableClass.includeCustomMappers.Fixed error when using non-literal values in @MappableValue().
Fixed error when using non-literal values in @MappableValue().
The builder now respects basic initializer expressions of a constructor. This makes it possible to do field renaming or assigning to private fields without requiring an additional getter matching the parameter.
The following is now supported out of the box:
class MyClass {
MyClass(int value, {String? name})
// Effectively renaming 'value' to 'data'.
: data = value,
// Assigning to a private field + having a null fallback.
_name = name ?? 'Unnamed';
final int value;
final String _name;
Fixed encoding of a map now returns a Map<String, dynamic> where possible
(instead of a Map<dynamic, dynamic>)
Fixed generic decoding when using generic superclass.
Fixed bug with undetermined includeSubClasses.
includeSubClasses.Breaking : Generated mappers no longer have a .container property. This was removed in favor of the new MapperContainer.globals container.
Breaking: Generated mappers no longer have a .container property. This was removed in favor
of the new MapperContainer.globals container.
// Instead of this:
var value = MyClassMapper.container.fromValue(...);
// Do this:
var value = MapperContainer.globals.fromValue(...);Mapper initialization and usage is now simplified to the following:
MyClassMapper.fromMap or myClass.toMap()) no additionalMapperContainer.globals.fromMap<MyClass>()) theMyClassMapper.ensureInitialized().Breaking: Changed internal mapper implementation which causes any custom mapper to break.
MapperElementBase class.MappingContext being passed to mapper methods.See docs on how to use custom mappers in v3.
Breaking: Removed @MappableLib.createCombinedContainer in favor of @MappableLib.generateInitializerForScope.
Instead of generating a new container, v3 generates an initialization function for all mappers. Use it early on in your
application:
@MappableLib(generateInitializerForScope: InitializerScope.package)
library main;
import 'main.init.dart';
void main() {
initializeMappers();
...
}Breaking: Improved support and features for .copyWith.
.copyWith.apply() method to .copyWith.$update()..copyWith.$merge() and .copyWith.$delta().You can now use .copyWith with either an existing instance using .$merge or a map of values using .$delta.
@MappableClass()
class A with AMappable {
A(this.a, this.b);
int? a;
int? b;
}
void main() {
var a = A(1, null);
var c = a.copyWith.$merge(A(null, 2));
assert(c == A(1, 2));
var d = a.copyWith.$delta({'b': 2});
assert(d == A(1, 2));
}Breaking: Removed CheckTypesHook in favor of discriminator functions.
You can now use a custom predicate function as the discriminatorValue of a class. This function can check
whether the encoded value should be decoded to this subclass and return a boolean.
@MappableClass()
abstract class A with AMappable {
A();
}
@MappableClass(discriminatorValue: B.checkType)
class B extends A with BMappable {
B();
/// checks if [value] should be decoded to [B]
static bool checkType(value) {
return value is Map && value['isB'] == true;
}
}
@MappableClass(discriminatorValue: C.checkType)
class C extends A with CMappable {
C();
/// checks if [value] should be decoded to [C]
static bool checkType(value) {
return value is Map && value['isWhat'] == 'C';
}
}Added support for serializing fields that are not part of the constructor
when annotated with @MappableField().
Added EncodingOptions to toValue method.
Added support for third-party models by using annotated typedefs.
Added renameMethods to build options.
Improved performance of generated encoding and decoding methods.
For a detailed migration guide, see this issue.
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Fixed an analysis error when using core interfaces.
Fixed generated container for private libraries.
Mappers are now generated for each file containing annotated classes. This removes the need to specify entry points in the build.yaml .
Mappers are now generated for each file containing annotated classes. This removes the
need to specify entry points in the build.yaml.
This is now similar to how packages like
json_serializableorfreezedgenerate code.
part files and need to be included as such.<MyClass>Mappable mixin.Mapper each class has its own <ClassName>Mapper.
@MappableLib(createCombinedContainer: true).@CustomMapper annotation in favor of includeCustomMappers property on @MappableClass().For a detailed migration guide, see this issue.
Documentation is now separated from the README using the official pub.dev documentation topics.
Find the new documentation here
Improvements in performance and support for generics and inheritance.
Added the [CheckTypesHook] to allow for custom discriminator checks on subclasses in a
polymorphic class structure.
CopyWith is now more powerful and also works for generic or polymorphic classes, while being
completely type-safe.
When called on a superclass, the concrete subtype will be retained through a
.copyWith call, which also respects generics:
// with `class A` and `class B<T> extends A`
A a = B<int>(); // static type A, dynamic type B<int>
// signature will be `A copyWith()`, so static type A
A a2 = a.copyWith();
// this will still resolve to a dynamic type of B<int>
assert(a2 is B<int>);Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Added support for 2.17 super parameters
2.17 super parametersYour coding agent can read these notes before it upgrades. Set up the MCP server →