Callable Mapping

Delegate target field computation to a function using callable:.

Callable Mapping

The callable: parameter on @Mapping lets you delegate computing a target field's value to a top-level function. The generator calls the function and assigns its return value to the target field.

Basic Callable

Define a top-level function and reference it as the callable:

class SourceObject {
  final String name;
  final int price;
  const SourceObject(this.name, this.price);
}

class TargetObject {
  final String name;
  final int price;
  const TargetObject(this.name, this.price);
}

int _doublePrice(dynamic price) => price * 2;

@Mapper()
abstract class PriceMapper {
  @Mapping(target: 'price', callable: _doublePrice)
  TargetObject toTarget(SourceObject source);
}

Generated:

@override
TargetObject toTarget(SourceObject source) {
  return TargetObject(
    name: source.name,
    price: _doublePrice(source.price),
  );
}

Callable with BuiltValue

callable: works with BuiltValue targets too:

@Mapping(target: 'price', callable: _doublePrice)
BuiltObject toBuiltObject(SourceObject source);

Generated uses the builder pattern:

@override
BuiltObject toBuiltObject(SourceObject source) {
  return BuiltObject((b) => b
    ..name = source.name
    ..price = _doublePrice(source.price));
}

Combining with Other Mappings

Other @Mapping annotations on the same method are unaffected — each one independently controls its target field:

@Mapper()
abstract class OrderMapper {
  @Mapping(target: 'total', callable: _calculateTotal)
  @Mapping(target: 'currency', constant: "'USD'")
  @Mapping(target: 'internalRef', ignore: true)
  OrderSummary toSummary(OrderInput order);
}

Mutual Exclusion Rules

callable: cannot be combined with:

Forbidden CombinationReason
callable + constantBoth provide the value
callable + defaultValueBoth provide the value
callable + expressionBoth compute the value
callable + conditionExpressionBoth control the output flow

Callable with Dot Notation Source

Use dot notation in source: to pass a nested field to the callable:

class Order {
  final Address address;
  const Order(this.address);
}

class Address {
  final String city;
  final String zip;
  const Address(this.city, this.zip);
}

class OrderSummary {
  final String location;
  const OrderSummary(this.location);
}

String _formatLocation(dynamic city) => city.toUpperCase();

@Mapper()
abstract class OrderMapper {
  @Mapping(target: 'location', source: 'address.city', callable: _formatLocation)
  OrderSummary toSummary(Order order);
}

Generated: _formatLocation(order.address.city).

Callable with Multiple Parameters

Use comma-separated field names in source: to pass multiple arguments:

class PersonSource {
  final String firstName;
  final String lastName;
  const PersonSource(this.firstName, this.lastName);
}

class PersonTarget {
  final String fullName;
  const PersonTarget(this.fullName);
}

String _merge(dynamic first, dynamic last) => '$first $last';

@Mapper()
abstract class PersonMapper {
  @Mapping(target: 'fullName', source: 'firstName,lastName', callable: _merge)
  PersonTarget toTarget(PersonSource source);
}

Generated: _merge(source.firstName, source.lastName).

Each comma-separated part is resolved as a field on the source parameter. You can also combine dot notation with comma separation (e.g., source: 'address.city,address.zip').

Function Signature Requirements

The callable must be a top-level function (not a method). The generator passes the relevant source field value(s) as arguments — a single field for basic callables, or multiple fields when using comma-separated sources. The return type must be assignable to the target field's type.

See Also