avoid_not_encodable_in_to_json
Flags a value in a toJson map that jsonEncode cannot serialize — a DateTime, an enum, or a nested model with no toJson of its own. The diagnostic names the offending type.
jsonEncode accepts only num, String, bool, null, List and Map; anything else throws JsonUnsupportedObjectError. The type system does not help, because Map<String, dynamic> accepts every value — so the mistake compiles cleanly and fails only when the map is actually encoded, usually in another layer on a path the tests do not cover.
enum Status { draft, published }
class Event { const Event(this.createdAt, this.status);
final DateTime createdAt; final Status status;
Map<String, dynamic> toJson() => { 'createdAt': createdAt, // throws at encode time 'status': status, // enums are not encodable either };}Convert each value to something jsonEncode understands:
enum Status { draft, published }
class Event { const Event(this.createdAt, this.status);
final DateTime createdAt; final Status status;
Map<String, dynamic> toJson() => { 'createdAt': createdAt.toIso8601String(), 'status': status.name, };}A nested model needs its own toJson
Section titled “A nested model needs its own toJson”jsonEncode reaches a nested object through its toEncodable hook, so a model that declares toJson is accepted as a value:
class Address { const Address(this.city);
final String city;
Map<String, dynamic> toJson() => {'city': city};}
class Order { const Order(this.address);
final Address address;
// Accepted — Address declares toJson Map<String, dynamic> toJson() => {'address': address};}A model without one is reported, which is the useful part: it catches the class you forgot to give a toJson before the encode does.
Collections are checked through their element type
Section titled “Collections are checked through their element type”// Don't — List<DateTime> is reportedMap<String, dynamic> toJson() => {'reminders': reminders};
// DoMap<String, dynamic> toJson() => { 'reminders': [for (final r in reminders) r.toIso8601String()],};Allowing a type your serializer handles
Section titled “Allowing a type your serializer handles”A project with a JsonConverter for a value type can name it, so the rule stops reporting what the serializer already knows how to write:
rules: avoid_not_encodable_in_to_json: allowed_types: [Decimal, Uint8List]// Accepted with the config aboveMap<String, dynamic> toJson() => {'amount': amount}; // amount is a DecimalSee also: dart:convert jsonEncode, JsonUnsupportedObjectError
Known limitations
Section titled “Known limitations”Collections are checked through their type arguments, so List<DateTime> is reported while List<String> is not. A Map’s values are checked; its keys are not — that is a blind spot in this rule, not a safe case. jsonEncode does not stringify non-String keys, it throws: both jsonEncode({1: 'x'}) and jsonEncode({DateTime(2020): 'x'}) raise JsonUnsupportedObjectError. Only Map<String, …> encodes.
dynamic and Object values are never reported — the runtime value may well be encodable, so any report would be guesswork. Type parameters are skipped for the same reason.
Only map literals returned directly from toJson are inspected. A map built up statement by statement, or returned from a helper, is not analysed.
Turning this rule off
Section titled “Turning this rule off”This rule is in the recommended preset, so it is on with
preset: recommended or preset: opinionated. Add it to preset: core with
avoid_not_encodable_in_to_json: true.
To turn it off:
rules: avoid_not_encodable_in_to_json: falseTo keep the rule on but skip certain paths, use per-rule exclude.
Options
Section titled “Options”many_lints: rules: avoid_not_encodable_in_to_json: allowed_types: [Decimal, Uint8List]rules: avoid_not_encodable_in_to_json: allowed_types: [Decimal, Uint8List]| Option | Type | Default | Description |
|---|---|---|---|
allowed_types |
list of strings | [] |
Type names to treat as encodable, for projects whose serializer handles them through a custom converter |
Related rules
Section titled “Related rules”prefer_correct_json_casts— Cast JSON values to nullable types.avoid_accessing_collections_by_constant_index— Avoid accessing a collection by a constant index inside a loop.avoid_collection_equality_checks— Avoid comparing collections with == or != as it checks reference equality, not contents.avoid_collection_methods_with_unrelated_types— Avoid calling collection methods with arguments whose types are unrelated to the collection’s type parameter.