import 'package:json_annotation/json_annotation.dart'; /// Decodes server lists element by element so one entry the model cannot map /// (a field the server dropped, an enum value it added) is skipped and /// recorded instead of failing the whole response and with it the screen. /// /// Skipped entries are collected per isolate; the API layer drains them with /// [drainDecodeWarnings] and reports them, so a drift in the server's format /// still reaches us without taking the feature down for the user. final List _warnings = []; List decodeListLenient( Object? raw, T Function(Map) fromJson, { required String what, }) { final items = []; if (raw is! List) { throw FormatException( 'expected a list of ${what}s, got ${raw.runtimeType}', ); } for (final entry in raw) { try { items.add(fromJson(entry as Map)); } on CheckedFromJsonException catch (e) { _warnings.add('$what: $e'); } on TypeError catch (e) { _warnings.add('$what: $e'); } } return items; } Set decodeSetLenient( Object? raw, T Function(Map) fromJson, { required String what, }) => decodeListLenient(raw, fromJson, what: what).toSet(); /// Returns and clears the entries skipped since the last call. List drainDecodeWarnings() { final out = List.of(_warnings); _warnings.clear(); return out; }