NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
pub.dev · #544 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
Release timing varies
gaps range from 9 days to 7 months
Nearly every release is documented
notes for 56 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
5 years old
128 releases · first in 2021
One column per quarter.
Add support for Primary Constructors.
Bump analyzer to >=10.0.0 <12.0.0.
analyzer to >=10.0.0 <12.0.0.Added firstWhere to ListCopyWith for chaining copyWith calls on a list element based on a predicate function.
firstWhere to ListCopyWith for chaining copyWith calls on a list element based on a predicate function.useNodoc option for excluding generated classes from dartdoc output.Record mappers now correctly uses hooks specified on the @MappableRecord annotation.
@MappableRecord annotation.initializeMappers() method.Add support for self-referencing generics (e.g. T extends Comparable )
T extends Comparable<T>)// dart format off.sdk: >=3.7.0.Added shallowEncoding option to @MappableClass().
shallowEncoding option to @MappableClass().includeTypeId option to @MappableClass().- Require sdk: >=3.6.0.
sdk: >=3.6.0.Added MapperContainer.typeIdKey to support changing the '__type' key.
MapperContainer.typeIdKey to support changing the '__type' key.Added support for reusing annotations as constant variables.
SimpleMapper1Bounded and SimpleMapper2Bounded for custom bounded generic types.Added CaseStyle.upperSnakeCase.
CaseStyle.upperSnakeCase.- Performance improvements. - Updated docs.
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
Improved migration docs regarding json_serializable and the difference of toJson().
json_serializable and the difference of toJson().Make DateTime encoding configurable through DateTimeMapper.encodingMode.
DateTime encoding configurable through DateTimeMapper.encodingMode.Handle bounded nested type parameters in subclasses.
- Fixed set equality.
Fixed unexpected type error when decoding null.
null.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.
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 dependency conflict with package:collection.
package:collection.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
Nothing published for this version
Fixed typo in readme (by @timmaffett)
Fixed yet another unresolved type bug.
Fixed unresolved type bug with custom mappers.
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
Added support for 2.17 super parameters
2.17 super parametersImproved Readme for constructor utilization
- Updated description
Deprecated the String toStringValue() extension method in favor of the more general dynamic toValue()
ValuesMode.named and ValuesMode.indexed for automatic generation of encoded values@MappableValue(myCustomValue) on an enum value to specify a custom encoded valueString toStringValue() extension method in favor of the more general dynamic toValue()Fixed issue with minified standard types on web
Fixed unrecognized type issue for equals, hashCode and toString methods
equals, hashCode and toString methodsImproved resolving of constructor parameters, which fixed various issues in copyWith and toMap methods
copyWith and toMap methodsLarge refactoring and restructuring
Large refactoring and restructuring
dart_mappable and dart_mappable_builderMapper is now a singleton class
fromValue, toValue and all other methods are now instance methods accessible with Mapper.i.fromValue()Improved Readme, added How to use section and documented copyWith functionalities
Added @MappableLib() annotation and moved library-level configuration logic from build options to annotation properties
Switched to using the type_plus package for internal handling of generics
Added ChainedHooks, UnescapeNewlinesHooks and EmptyToNullHooks
Added descriptive and comprehensible exception handling
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →