Convert Object
A comprehensive type conversion toolkit for Dart & Flutter Fluent API • Safe
try*variants • Collections • Enums • Dates/Numbers/URIs • JSON helpers • Ergonomic map/list extensions
Table of contents
Why convert_object?
convert_object gives you a single, consistent API to turn loosely‑typed or dynamic data (maps, lists, JSON, strings) into strongly‑typed values — with:
- Fluent conversion (
obj.convert.toInt()) and static helpers (ConvertObject.toInt(obj)). - Safe
try*variants that never throw (returnnullor a default). - Collections: convert to
List<T>,Set<T>,Map<K,V>with custom element/key/value converters. - Enums: robust parsers (
byName,caseInsensitive,byIndex, fallback). - Dates: smart auto‑detection, explicit formats & locales, clear local/UTC behavior.
- Numbers: forgiving parsing (
"1 234.56","(1,234)"), localized formats. - URIs: parse http/https + detect emails and phone numbers →
mailto:/tel:. - Ergonomic map/list extensions for inner selection and fallbacks.
- Helpful exceptions (
ConversionException) with context for debugging.
Install
dependencies:
convert_object: ^latest
Import:
import 'package:convert_object/convert_object.dart';
Quick start
import 'package:convert_object/convert_object.dart';
void main() {
dynamic data = {
'id': '42',
'price': '1,234.56',
'when': '2024-02-29T10:15:00Z',
'site': 'https://example.com',
'tags': ['1', 2, '3'],
'user': {'email': 'alice@example.com'},
'status': 'Active',
};
// Static facade
final id = ConvertObject.toInt(data, mapKey: 'id'); // 42
final price = ConvertObject.toDouble(data, mapKey: 'price'); // 1234.56
final when = ConvertObject.toDateTime(data, mapKey: 'when', utc: true);
final site = ConvertObject.toUri(data, mapKey: 'site'); // Uri
final tags = ConvertObject.toList<int>(data, mapKey: 'tags'); // [1,2,3]
final email = ConvertObject.toUri(data, mapKey: 'user', listIndex: null,
defaultValue: null); // mailto:alice@example.com
// Fluent API
final asBool = 'ok'.convert.toBool(); // true
final maybeNum = 'oops'.convert.tryToNum(); // null
// Enums
enum Status { Active, Disabled }
final s = ConvertObject.toEnum<Status>(data['status'],
parser: EnumParsers.byName(Status.values)); // Status.Active
print([id, price, when, site, tags, asBool, maybeNum, s]);
}
Core APIs
Static facade: ConvertObject
Backwards‑compatible, static helpers that cover primitives, dates, URIs, enums, collections, and generic routing.
Primitives
// Text
String ConvertObject.toText(obj, {mapKey, listIndex, defaultValue, converter});
String? ConvertObject.tryToText(obj, { ... });
// Numbers
num ConvertObject.toNum(obj, {format, locale, ...});
num? ConvertObject.tryToNum(obj, {format, locale, ...});
int ConvertObject.toInt(obj, {format, locale, ...});
int? ConvertObject.tryToInt(obj, {format, locale, ...});
double ConvertObject.toDouble(obj, {format, locale, ...});
double? ConvertObject.tryToDouble(obj, {format, locale, ...});
BigInt ConvertObject.toBigInt(obj, {...});
BigInt? ConvertObject.tryToBigInt(obj, {...});
// Bool (predictable truthiness; see below)
bool ConvertObject.toBool(obj, {defaultValue});
bool? ConvertObject.tryToBool(obj, {defaultValue});
// DateTime
DateTime ConvertObject.toDateTime(obj, {
format, locale, autoDetectFormat=false,
useCurrentLocale=false, utc=false, ...
});
DateTime? ConvertObject.tryToDateTime(obj, { ... });
// Uri (detects email/phone and builds mailto:/tel:)
Uri ConvertObject.toUri(obj, {defaultValue});
Uri? ConvertObject.tryToUri(obj, {defaultValue});
Collections
// Map
Map<K,V> ConvertObject.toMap<K,V>(obj, {
keyConverter, valueConverter, defaultValue
});
Map<K,V>? ConvertObject.tryToMap<K,V>(...);
// Set
Set<T> ConvertObject.toSet<T>(obj, {elementConverter, defaultValue});
Set<T>? ConvertObject.tryToSet<T>(...);
// List
List<T> ConvertObject.toList<T>(obj, {elementConverter, defaultValue});
List<T>? ConvertObject.tryToList<T>(...);
Enums
T ConvertObject.toEnum<T extends Enum>(obj, { required parser, defaultValue });
T? ConvertObject.tryToEnum<T extends Enum>(obj, { required parser, defaultValue });
Generic routing
T ConvertObject.toType<T>(obj); // supports bool,int,double,num,BigInt,String,DateTime,Uri
T? ConvertObject.tryToType<T>(obj);
All
to*methods throw aConversionExceptionon failure AlltryTo*methods never throw; they returnnull(or a provideddefaultValue)
Fluent API: Converter + .convert extension
Prefer writing code like this:
final value = someDynamic.convert
.withDefault(0)
.withConverter((v) => v is String ? v.trim() : v) // optional pre-transform
.toInt();
Key features:
.convert— extension onObject?returning aConverter.- Navigation helpers:
.fromMap(key),.fromList(index),.decoded(JSON decode if the source is aString). - Generic targets:
.to<T>(),.tryTo<T>(),.toOr(default). - Primitive shortcuts:
.toInt(),.tryToDouble(),.toDateTimeOr(fallback), etc. - Collections:
.toList<T>(elementConverter: ...),.toMap<K,V>(keyConverter: ..., valueConverter: ...).
Example:
final jsonText = '{"user": {"age": " 21 ", "email": "bob@example.com"}}';
final age = jsonText.convert.decoded
.fromMap('user')
.fromMap('age')
.withConverter((v) => v is String ? v.trim() : v)
.toInt(); // 21
final emailUri = jsonText.convert.decoded
.fromMap('user')
.fromMap('email')
.toUri(); // mailto:bob@example.com
Top‑level functions
All static methods also exist as free functions if you prefer shorter calls:
import 'package:convert_object/convert_object.dart';
final n = toInt('1,234'); // 1234
final dt = toDateTime('20240229'); // Feb 29, 2024 (local)
final list = toList<int>(['1', 2]); // [1,2]
Map/Iterable/Object extensions
Map
Ergonomic getters with inner selection and alternative keys:
final user = {'id': '42', 'joined': '29/02/2024', 'tags': ['1', 2, '3']};
final id = user.getInt('id'); // 42
final when = user.getDateTime('joined', locale: 'en_GB');
final tags = user.getList<int>('tags'); // [1,2,3]
// Try variants + alt keys
final name = user.tryGetText('name', alternativeKeys: ['username', 'handle']);
Available getters on Map<K,V> and Map<K,V>?:
get/tryGetText, get/tryGetInt, get/tryGetDouble, get/tryGetNum,
get/tryGetBool, get/tryGetBigInt, get/tryGetDateTime, get/tryGetUri,
get/tryGetList<T>, get/tryGetSet<T>, get/tryGetMap<K2,V2>, get/tryGetEnum<T>().
Quality‑of‑life:
valuesList, valuesSet, keysList, keysSet, and parsing helpers:
final model = map.parse<String, String, Object?>('payload', MyModel.fromJson);
final maybe = map.tryParse<String, Object?, Object?>('optional', MyModel.fromJson);
Iterable
final items = ['100', '200', 'oops', '300'];
// Positional conversions with optional inner selection
final a = items.getInt(0); // 100
final b = items.tryGetInt(2, alternativeIndices: [3, 1]); // 300 (falls back)
// Convert the whole iterable
final asInts = items.convertAll<int>(); // [100,200,Exception->throws at 'oops']
// Safer: try variants / element converters
final safe = items.mapList<int>((s) => toInt(s)); // [100,200,throws at 'oops']
final withTry = items.mapIndexedList((i, s) => tryToInt(s) ?? i); // [100,200,2,300]
// Set helpers
final union = {1,2,3}.intersect([3,4,5]); // {1,2,3,4,5} (legacy: name kept)
Object → Converter
someObj.convert.toBool();
Let extensions
final x = ' hello '.let((s) => s.trim()); // "hello"
final y = (null as String?).letOr((s) => s.length, defaultValue: 0); // 0
Enum helpers: EnumParsers
enum Mode { light, dark }
final parserByName = EnumParsers.byName(Mode.values);
final parserCaseInsensitive = EnumParsers.byNameCaseInsensitive(Mode.values);
final parserByIndex = EnumParsers.byIndex(Mode.values);
final parserWithFallback = EnumParsers.byNameOrFallback(Mode.values, Mode.light);
// Usage with ConvertObject
final m1 = ConvertObject.toEnum<Mode>('dark', parser: parserByName); // dark
final m2 = ConvertObject.toEnum<Mode>('DARK', parser: parserCaseInsensitive); // dark
final m3 = ConvertObject.toEnum<Mode>('oops', parser: parserWithFallback); // light
final m4 = ConvertObject.toEnum<Mode>(1, parser: parserByIndex); // dark
// Shortcuts from a list of enum values:
final byName = Mode.values.parser;
Results: ConversionResult<T>
A tiny monad to carry success/failure without throwing:
ConversionResult<int> parseAge(Object? v) {
try {
return ConversionResult.success(ConvertObject.toInt(v));
} on ConversionException catch (e) {
return ConversionResult.failure(e);
}
}
final res = parseAge('not a number');
final age = res.valueOr(0); // 0
res.error?.toString(); // Human‑readable diagnostic
Deep‑dive: Date & time parsing
toDateTime and friends support explicit formats (via intl) and a robust auto‑detect mode with predictable time‑zone semantics.
// Explicit format
final birth = ConvertObject.toDateTime('29/02/2024',
format: 'dd/MM/yyyy', locale: 'en_GB');
// Auto‑detect (set `autoDetectFormat: true`)
final a = ConvertObject.toDateTime('20240229', autoDetectFormat: true);
final b = ConvertObject.toDateTime('02/29/2024', autoDetectFormat: true, locale: 'en_US');
final c = ConvertObject.toDateTime('Thu, 20 Jun 2024 12:34:56 GMT',
autoDetectFormat: true, utc: true);
Auto‑detection priority (simplified):
- Unix epoch (
9–10digits = sec,12–13digits = ms;12digits guarded to avoidyyyyMMddHHmm). - ISO‑8601/RFC3339 (via
DateTime.parse). - HTTP date (
IMF-fixdate,GMT) → treated as UTC. - Slashed ambiguous (
MM/ddvsdd/MM) by locale (e.g.,en_USvsen_GB). - Compact numeric
yyyyMMdd[HHmm[ss]](spaces/underscores allowed). - Long names via
intl(e.g.,March 5, 2024). - Time‑only (
HH:mm[:ss]) → today’s date (local).
Time zone rules
- Calendar‑like inputs (no explicit offset) return local time by default; set
utc: trueto force UTC. - Instant‑like inputs (ISO with
Z/offsets, HTTP date, Unix epoch) preserve their UTC meaning; ifutc: falsewe convert back to local for convenience.
Numbers & booleans
Numbers
- Accepts inputs like
"1 234.56","1,234"," 123_456 ","(2,500)"(→-2500). - Localized parsing via
format+locale(usesintl:NumberFormat).
ConvertObject.toInt('1,234'); // 1234
ConvertObject.toNum('1.234,56', format: '#,##0.##', locale: 'de_DE'); // 1234.56
Booleans (asBool)
Predictable, explicit rules (case‑insensitive):
null → falsebool → valuenum → value > 0Stringtruthy:'true','1','yes','y','on','ok','t'Stringfalsy :'false','0','no','n','off','f'Stringnumeric → parsed then> 0- anything else →
false
final ok = 'OK'.convert.toBool(); // true
final nope = 'nope'.convert.toBool(); // false
URIs (http/mail/phone)
toUri understands:
- Regular URIs (
http,https,file, …) - Emails →
mailto:user@domain.tld - Phone numbers →
tel:+14155551234
ConvertObject.toUri('alice@example.com'); // mailto:alice@example.com
ConvertObject.toUri('+1 (415) 555-1234'); // tel:+14155551234
ConvertObject.toUri('https://example.com'); // Uri
Parsing safeguards (invalid host/path) are enforced. Use tryToUri or defaultValue to avoid throwing.
JSON + pretty utilities
A few helpers are re‑exported to make JSON‑heavy flows ergonomic:
// Strings -> try to decode JSON else return the original text
final dynamic decoded = '{"a":1}'.tryDecode(); // Map<String,dynamic>
// Map/Iterable pretty JSON
final pretty = {'a': 1, 'b': { 'c': 3 }}.encodedJsonText;
/* Also available:
- Iterable: .encodedJson / .encodedJsonWithIndent()
- Any object: .encode(toEncodable: ...)
*/
Error handling & debugging
All throwing conversions use a single exception type:
try {
final n = ConvertObject.toInt('oops');
} on ConversionException catch (e) {
print(e); // filtered context (safe + concise)
// print(e.fullReport()); // full JSON context + stack (verbose)
}
ConversionException records method, objectType, targetType, map/list navigation context (mapKey, listIndex), formatting/locale options, and any caller‑supplied debug info. Heavy values are summarized to keep logs readable.
Prefer the
tryTo*family or pass adefaultValuewhen failures are expected.
Advanced usage & recipes
1) Converting nested and mixed collections
final input = {
'prices': ['1.2', 3, '4.56'],
'attrs': {'a': '1', 'b': 2.5, 'c': '3'},
};
final prices = ConvertObject.toList<double>(input, mapKey: 'prices'); // [1.2,3.0,4.56]
final attrs = ConvertObject.toMap<String, int>(
input,
mapKey: 'attrs',
keyConverter: (k) => k.toString(),
valueConverter: (v) => v is int ? v : ConvertObject.toInt(v),
); // {'a':1,'b':2,'c':3}
2) Model parsing with map extensions
class User {
final int id;
final String email;
final DateTime createdAt;
User(this.id, this.email, this.createdAt);
factory User.fromJson(Map<String, Object?> json) => User(
json.getInt('id'),
json.getText('email', alternativeKeys: ['mail']),
json.getDateTime('created_at',
autoDetectFormat: true, useCurrentLocale: true),
);
}
3) Safe list indexing with fallbacks
final row = ['name', null, '42'];
final id = row.tryGetInt(1, alternativeIndices: [2]) ?? -1; // 42
4) Enum parsing shortcuts
enum Role { admin, editor, viewer }
final role = ConvertObject.toEnum<Role>(
'EDITOR',
parser: Role.values.parserCaseInsensitive,
);
Migration from dart_helper_utils
This package provides a backwards‑compatible static facade named ConvertObject with the original method names and signatures, while offering a complete, modernized implementation.
Notable notes:
- The list/set/map conversion logic now auto‑decodes JSON strings when it makes sense (e.g., a
Stringholding a JSON array/map). - The
Iterable.intersectextension mirrors historical behavior from DHU where the method name implied intersection but effectively merged elements (set union). That name is preserved for compatibility. - Boolean parsing merges rules from legacy DHU and this library into a single, explicit policy.
- Prefer the new fluent API (
.convert) for readable pipelines.
Performance notes
-
Passing
format/localefor numbers or dates creates anintlformatter on call. In tight loops, consider:- Normalizing inputs (e.g., pre‑trim, pre‑clean) and using non‑formatted
toNum/toInt/toDoublewhere possible. - Supplying an elementConverter for collections to avoid repeated generic routing.
- Normalizing inputs (e.g., pre‑trim, pre‑clean) and using non‑formatted
-
try*methods are exception‑free and cheaper when failures are expected. -
toList<T>and friends can convert single values by wrapping them (TorList<T>); use element converters for maximal control.
FAQ
Q: What happens if a conversion fails?
A: to* methods throw ConversionException with context; tryTo* return null (or your defaultValue).
Q: How are ambiguous dates like 02/03/2024 handled?
A: By locale (en_US → MM/dd, most others → dd/MM). For deterministic behavior, pass format.
Q: Does toUri accept plain emails/phone numbers?
A: Yes. Emails become mailto:; phone numbers become tel: with digits normalized.
Q: Which types does toType<T> handle specially?
A: bool, int, double, num, BigInt, String, DateTime, Uri. Other T values are cast directly if already of type T; otherwise a ConversionException is thrown.
Contributing
Issues and PRs are welcome!
Please include tests where possible and keep APIs consistent with the existing style (to* / tryTo*, defaults, and context‑rich errors).
License
This project is open‑source. See LICENSE in the repository for details.
API reference
See the generated API docs on pub.flutter-io.cn:
https://pub.flutter-io.cn/documentation/convert_object/latest/
Appendix — Full API cheat‑sheet
Type aliases
typedef ElementConverter<T> = T Function(Object? element);
typedef DynamicConverter<T> = T Function(Object? value);
Static facade — ConvertObject
// Text
String ConvertObject.toText(
dynamic object, {dynamic mapKey, int? listIndex, String? defaultValue,
ElementConverter<String>? converter});
String? ConvertObject.tryToText(
dynamic object, {dynamic mapKey, int? listIndex, String? defaultValue,
ElementConverter<String>? converter});
// Numbers
num ConvertObject.toNum(
dynamic object, {dynamic mapKey, int? listIndex, String? format, String? locale,
num? defaultValue, ElementConverter<num>? converter});
num? ConvertObject.tryToNum(
dynamic object, {dynamic mapKey, int? listIndex, String? format, String? locale,
num? defaultValue, ElementConverter<num>? converter});
int ConvertObject.toInt(
dynamic object, {dynamic mapKey, int? listIndex, String? format, String? locale,
int? defaultValue, ElementConverter<int>? converter});
int? ConvertObject.tryToInt(
dynamic object, {dynamic mapKey, int? listIndex, String? format, String? locale,
int? defaultValue, ElementConverter<int>? converter});
double ConvertObject.toDouble(
dynamic object, {dynamic mapKey, int? listIndex, String? format, String? locale,
double? defaultValue, ElementConverter<double>? converter});
double? ConvertObject.tryToDouble(
dynamic object, {dynamic mapKey, int? listIndex, String? format, String? locale,
double? defaultValue, ElementConverter<double>? converter});
// BigInt
BigInt ConvertObject.toBigInt(
dynamic object, {dynamic mapKey, int? listIndex, BigInt? defaultValue,
ElementConverter<BigInt>? converter});
BigInt? ConvertObject.tryToBigInt(
dynamic object, {dynamic mapKey, int? listIndex, BigInt? defaultValue,
ElementConverter<BigInt>? converter});
// Bool (never throws; defaults to false if not convertible)
bool ConvertObject.toBool(
dynamic object, {dynamic mapKey, int? listIndex, bool? defaultValue,
ElementConverter<bool>? converter});
bool? ConvertObject.tryToBool(
dynamic object, {dynamic mapKey, int? listIndex, bool? defaultValue,
ElementConverter<bool>? converter});
// DateTime
DateTime ConvertObject.toDateTime(
dynamic object, {
dynamic mapKey, int? listIndex, String? format, String? locale,
bool autoDetectFormat=false, bool useCurrentLocale=false, bool utc=false,
DateTime? defaultValue, ElementConverter<DateTime>? converter
});
DateTime? ConvertObject.tryToDateTime(
dynamic object, {
dynamic mapKey, int? listIndex, String? format, String? locale,
bool autoDetectFormat=false, bool useCurrentLocale=false, bool utc=false,
DateTime? defaultValue, ElementConverter<DateTime>? converter
});
// Uri (supports email→mailto and phone→tel)
Uri ConvertObject.toUri(
dynamic object, {dynamic mapKey, int? listIndex, Uri? defaultValue,
ElementConverter<Uri>? converter});
Uri? ConvertObject.tryToUri(
dynamic object, {dynamic mapKey, int? listIndex, Uri? defaultValue,
ElementConverter<Uri>? converter});
// Collections
Map<K,V> ConvertObject.toMap<K,V>(
dynamic object, {dynamic mapKey, int? listIndex, Map<K,V>? defaultValue,
ElementConverter<K>? keyConverter, ElementConverter<V>? valueConverter});
Map<K,V>? ConvertObject.tryToMap<K,V>(
dynamic object, {dynamic mapKey, int? listIndex, Map<K,V>? defaultValue,
ElementConverter<K>? keyConverter, ElementConverter<V>? valueConverter});
Set<T> ConvertObject.toSet<T>(
dynamic object, {dynamic mapKey, int? listIndex, Set<T>? defaultValue,
ElementConverter<T>? elementConverter});
Set<T>? ConvertObject.tryToSet<T>(
dynamic object, {dynamic mapKey, int? listIndex, Set<T>? defaultValue,
ElementConverter<T>? elementConverter});
List<T> ConvertObject.toList<T>(
dynamic object, {dynamic mapKey, int? listIndex, List<T>? defaultValue,
ElementConverter<T>? elementConverter});
List<T>? ConvertObject.tryToList<T>(
dynamic object, {dynamic mapKey, int? listIndex, List<T>? defaultValue,
ElementConverter<T>? elementConverter});
// Enums
T ConvertObject.toEnum<T extends Enum>(
dynamic object, {required T Function(dynamic) parser,
dynamic mapKey, int? listIndex, T? defaultValue, Map<String, dynamic>? debugInfo});
T? ConvertObject.tryToEnum<T extends Enum>(
dynamic object, {required T Function(dynamic) parser,
dynamic mapKey, int? listIndex, T? defaultValue, Map<String, dynamic>? debugInfo});
// Generic routing
T ConvertObject.toType<T>(dynamic object);
T? ConvertObject.tryToType<T>(dynamic object);
// Testing-helper (only for tests)
@visibleForTesting
Map<String, dynamic> ConvertObject.buildParsingInfo({ ... });
Top‑level functions (mirror the static API)
// Text
String toText(dynamic object, {Object? mapKey, int? listIndex, String? defaultValue,
String Function(Object?)? converter});
String? tryToText(dynamic object, {Object? mapKey, int? listIndex, String? defaultValue,
String Function(Object?)? converter});
// Numbers
num toNum(dynamic object, {Object? mapKey, int? listIndex, String? format, String? locale,
num? defaultValue, num Function(Object?)? converter});
num? tryToNum(dynamic object, {Object? mapKey, int? listIndex, String? format, String? locale,
num? defaultValue, num Function(Object?)? converter});
int toInt(dynamic object, {Object? mapKey, int? listIndex, String? format, String? locale,
int? defaultValue, int Function(Object?)? converter});
int? tryToInt(dynamic object, {Object? mapKey, int? listIndex, String? format, String? locale,
int? defaultValue, int Function(Object?)? converter});
double toDouble(dynamic object, {Object? mapKey, int? listIndex, String? format, String? locale,
double? defaultValue, double Function(Object?)? converter});
double? tryToDouble(dynamic object, {Object? mapKey, int? listIndex, String? format, String? locale,
double? defaultValue, double Function(Object?)? converter});
// BigInt
BigInt toBigInt(dynamic object, {Object? mapKey, int? listIndex, BigInt? defaultValue,
BigInt Function(Object?)? converter});
BigInt? tryToBigInt(dynamic object, {Object? mapKey, int? listIndex, BigInt? defaultValue,
BigInt Function(Object?)? converter});
// Bool
bool toBool(dynamic object, {Object? mapKey, int? listIndex, bool? defaultValue,
bool Function(Object?)? converter});
bool? tryToBool(dynamic object, {Object? mapKey, int? listIndex, bool? defaultValue,
bool Function(Object?)? converter});
// DateTime
DateTime toDateTime(dynamic object, {
Object? mapKey, int? listIndex, String? format, String? locale,
bool autoDetectFormat=false, bool useCurrentLocale=false, bool utc=false,
DateTime? defaultValue, DateTime Function(Object?)? converter});
DateTime? tryToDateTime(dynamic object, {
Object? mapKey, int? listIndex, String? format, String? locale,
bool autoDetectFormat=false, bool useCurrentLocale=false, bool utc=false,
DateTime? defaultValue, DateTime Function(Object?)? converter});
// Uri
Uri toUri(dynamic object, {Object? mapKey, int? listIndex, Uri? defaultValue,
Uri Function(Object?)? converter});
Uri? tryToUri(dynamic object, {Object? mapKey, int? listIndex, Uri? defaultValue,
Uri Function(Object?)? converter});
// Collections
Map<K,V> toMap<K,V>(dynamic object, {Object? mapKey, int? listIndex, Map<K,V>? defaultValue,
K Function(Object?)? keyConverter, V Function(Object?)? valueConverter});
Map<K,V>? tryToMap<K,V>(dynamic object, {Object? mapKey, int? listIndex, Map<K,V>? defaultValue,
K Function(Object?)? keyConverter, V Function(Object?)? valueConverter});
Set<T> toSet<T>(dynamic object, {Object? mapKey, int? listIndex, Set<T>? defaultValue,
T Function(Object?)? elementConverter});
Set<T>? tryToSet<T>(dynamic object, {Object? mapKey, int? listIndex, Set<T>? defaultValue,
T Function(Object?)? elementConverter});
List<T> toList<T>(dynamic object, {Object? mapKey, int? listIndex, List<T>? defaultValue,
T Function(Object?)? elementConverter});
List<T>? tryToList<T>(dynamic object, {Object? mapKey, int? listIndex, List<T>? defaultValue,
T Function(Object?)? elementConverter});
// Generic
T toType<T>(dynamic object);
T? tryToType<T>(dynamic object);
Fluent API — Converter + .convert extension
// Entry point
extension ConvertObjectExtension on Object? {
Converter get convert;
}
class Converter {
const Converter(Object? value, {Object? defaultValue, DynamicConverter<dynamic>? customConverter});
// Options
Converter withDefault(Object? value);
Converter withConverter(DynamicConverter<dynamic> converter);
// Navigation
Converter fromMap(Object? key);
Converter fromList(int index);
Converter get decoded; // JSON-decodes if source is a String
// Generic targets
T to<T>();
T? tryTo<T>();
T toOr<T>(T defaultValue);
// Primitive shortcuts
String toText(); String? tryToText(); String toTextOr(String defaultValue);
num toNum(); num? tryToNum(); num toNumOr(num defaultValue);
int toInt(); int? tryToInt(); int toIntOr(int defaultValue);
double toDouble(); double? tryToDouble(); double toDoubleOr(double defaultValue);
bool toBool(); bool? tryToBool(); bool toBoolOr(bool defaultValue);
BigInt toBigInt(); BigInt? tryToBigInt(); BigInt toBigIntOr(BigInt defaultValue);
DateTime toDateTime(); DateTime? tryToDateTime(); DateTime toDateTimeOr(DateTime defaultValue);
Uri toUri(); Uri? tryToUri(); Uri toUriOr(Uri defaultValue);
// Collections
List<T> toList<T>({DynamicConverter<T>? elementConverter});
List<T>? tryToList<T>({DynamicConverter<T>? elementConverter});
Set<T> toSet<T>({DynamicConverter<T>? elementConverter});
Set<T>? tryToSet<T>({DynamicConverter<T>? elementConverter});
Map<K,V> toMap<K,V>({DynamicConverter<K>? keyConverter, DynamicConverter<V>? valueConverter});
Map<K,V>? tryToMap<K,V>({DynamicConverter<K>? keyConverter, DynamicConverter<V>? valueConverter});
}
Map extensions
// Non-nullable Map<K,V>
extension MapConversionX<K, V> on Map<K, V> {
// Getters with inner selection and alternative keys
String getText(K key, {List<K>? alternativeKeys, dynamic innerKey, int? innerListIndex, String? defaultValue});
int getInt(K key, {List<K>? alternativeKeys, dynamic innerKey, int? innerListIndex, int? defaultValue, String? format, String? locale});
double getDouble(K key, {List<K>? alternativeKeys, dynamic innerKey, int? innerListIndex, double? defaultValue, String? format, String? locale});
num getNum(K key, {List<K>? alternativeKeys, dynamic innerKey, int? innerListIndex, num? defaultValue, String? format, String? locale, ElementConverter<num>? converter});
bool getBool(K key, {List<K>? alternativeKeys, dynamic innerKey, int? innerListIndex, bool? defaultValue});
BigInt getBigInt(K key, {List<K>? alternativeKeys, dynamic innerKey, int? innerListIndex, BigInt? defaultValue});
DateTime getDateTime(K key, {List<K>? alternativeKeys, dynamic innerKey, int? innerListIndex,
String? format, String? locale, bool autoDetectFormat=false, bool useCurrentLocale=false, bool utc=false, DateTime? defaultValue});
Uri getUri(K key, {List<K>? alternativeKeys, dynamic innerKey, int? innerListIndex, Uri? defaultValue});
List<T> getList<T>(K key, {List<K>? alternativeKeys, dynamic innerKey, int? innerListIndex, List<T>? defaultValue});
Set<T> getSet<T>(K key, {List<K>? alternativeKeys, dynamic innerKey, int? innerListIndex, Set<T>? defaultValue});
Map<K2,V2> getMap<K2,V2>(K key, {List<K>? alternativeKeys, dynamic innerKey, int? innerListIndex, Map<K2,V2>? defaultValue});
T getEnum<T extends Enum>(K key, {required T Function(dynamic) parser,
List<K>? alternativeKeys, dynamic innerKey, int? innerListIndex, T? defaultValue});
// Quality-of-life
List<V> get valuesList;
Set<V> get valuesSet;
List<K> get keysList;
Set<K> get keysSet;
// Parsing helpers
T parse<T, K2, V2>(K key, T Function(Map<K2, V2> json) converter);
T? tryParse<T, K2, V2>(K key, T Function(Map<K2, V2> json) converter);
}
// Nullable Map<K,V> → try* getters
extension NullableMapConversionX<K, V> on Map<K, V>? {
String? tryGetText(...);
int? tryGetInt(...);
double? tryGetDouble(...);
num? tryGetNum(...);
bool? tryGetBool(...);
BigInt? tryGetBigInt(...);
DateTime? tryGetDateTime(...);
Uri? tryGetUri(...);
List<T>? tryGetList<T>(...);
Set<T>? tryGetSet<T>(...);
Map<K2,V2>? tryGetMap<K2,V2>(...);
T? tryGetEnum<T extends Enum>(...);
}
Iterable extensions
// On Iterable<E>
extension IterableConversionX<E> on Iterable<E> {
// Positional getters (with optional inner map/list selection)
String getText(int index, {dynamic innerMapKey, int? innerIndex, String? defaultValue, ElementConverter<String>? converter});
int getInt(int index, {dynamic innerMapKey, int? innerIndex, String? format, String? locale, int? defaultValue, ElementConverter<int>? converter});
double getDouble(int index, {dynamic innerMapKey, int? innerIndex, String? format, String? locale, double? defaultValue, ElementConverter<double>? converter});
num getNum(int index, {dynamic innerMapKey, int? innerIndex, String? format, String? locale, num? defaultValue, ElementConverter<num>? converter});
bool getBool(int index, {dynamic innerMapKey, int? innerIndex, bool? defaultValue, ElementConverter<bool>? converter});
BigInt getBigInt(int index, {dynamic innerMapKey, int? innerIndex, BigInt? defaultValue, ElementConverter<BigInt>? converter});
DateTime getDateTime(int index, {dynamic innerMapKey, int? innerIndex, String? format, String? locale,
bool autoDetectFormat=false, bool useCurrentLocale=false, bool utc=false,
DateTime? defaultValue, ElementConverter<DateTime>? converter});
Uri getUri(int index, {dynamic innerMapKey, int? innerIndex, Uri? defaultValue, ElementConverter<Uri>? converter});
List<T> getList<T>(int index, {dynamic innerMapKey, int? innerIndex, List<T>? defaultValue});
Set<T> getSet<T>(int index, {dynamic innerMapKey, int? innerIndex, Set<T>? defaultValue});
Map<K2,V2> getMap<K2,V2>(int index, {dynamic innerMapKey, int? innerIndex, Map<K2,V2>? defaultValue});
T getEnum<T extends Enum>(int index, {required T Function(dynamic) parser,
dynamic innerMapKey, int? innerIndex, T? defaultValue});
// Bulk helpers
List<T> convertAll<T>(); // Convert all elements via toType<T>()
Set<E> toMutableSet({ElementConverter<E>? converter});
Set<E> intersect(Iterable<dynamic> other, {ElementConverter<E>? converter}); // union-like
// Mapping helpers (eager)
List<R> mapList<R>(R Function(E e) mapper, {ElementConverter<R>? converter});
List<R> mapIndexedList<R>(R Function(int i, E e) mapper, {ElementConverter<R>? converter});
}
// Nullable Iterable<E> → try* positional getters with fallbacks
extension NullableIterableConversionX<E> on Iterable<E>? {
String? tryGetText(int index, {List<int>? alternativeIndices, dynamic innerMapKey, int? innerIndex, String? defaultValue, ElementConverter<String>? converter});
int? tryGetInt(int index, {List<int>? alternativeIndices, dynamic innerMapKey, int? innerIndex, String? format, String? locale, int? defaultValue, ElementConverter<int>? converter});
double? tryGetDouble(int index, {List<int>? alternativeIndices, dynamic innerMapKey, int? innerIndex, String? format, String? locale, double? defaultValue, ElementConverter<double>? converter});
num? tryGetNum(int index, {List<int>? alternativeIndices, dynamic innerMapKey, int? innerIndex, String? format, String? locale, num? defaultValue, ElementConverter<num>? converter});
bool? tryGetBool(int index, {List<int>? alternativeIndices, dynamic innerMapKey, int? innerIndex, bool? defaultValue, ElementConverter<bool>? converter});
BigInt? tryGetBigInt(int index, {List<int>? alternativeIndices, dynamic innerMapKey, int? innerIndex, BigInt? defaultValue, ElementConverter<BigInt>? converter});
DateTime? tryGetDateTime(int index, {List<int>? alternativeIndices, dynamic innerMapKey, int? innerIndex,
String? format, String? locale, bool autoDetectFormat=false, bool useCurrentLocale=false, bool utc=false,
DateTime? defaultValue, ElementConverter<DateTime>? converter});
Uri? tryGetUri(int index, {List<int>? alternativeIndices, dynamic innerMapKey, int? innerIndex, Uri? defaultValue, ElementConverter<Uri>? converter});
List<T>? tryGetList<T>(int index, {List<int>? alternativeIndices, dynamic innerMapKey, int? innerIndex, List<T>? defaultValue});
Set<T>? tryGetSet<T>(int index, {List<int>? alternativeIndices, dynamic innerMapKey, int? innerIndex, Set<T>? defaultValue});
Map<K2,V2>? tryGetMap<K2,V2>(int index, {List<int>? alternativeIndices, dynamic innerMapKey, int? innerIndex, Map<K2,V2>? defaultValue});
T? tryGetEnum<T extends Enum>(int index, {required T Function(dynamic) parser,
List<int>? alternativeIndices, dynamic innerMapKey, int? innerIndex, T? defaultValue});
}
// Set helper
extension SetConvertToX<E> on Set<E>? {
Set<R> convertTo<R>();
}
Let extensions
extension LetExtension<T extends Object> on T {
R let<R>(R Function(T it) block);
}
extension LetExtensionNullable<T extends Object> on T? {
R? let<R>(R Function(T it) block);
R letOr<R>(R Function(T it) block, {required R defaultValue});
R? letNullable<R>(R? Function(T? it) block); // legacy-compat variant
}
Enum helpers — EnumParsers & shortcuts
class EnumParsers {
static T Function(dynamic) byName<T extends Enum>(List<T> values);
static T Function(dynamic) fromText<T>(T Function(String) fromText);
static T Function(dynamic) byNameOrFallback<T extends Enum>(List<T> values, T fallback);
static T Function(dynamic) byNameCaseInsensitive<T extends Enum>(List<T> values);
static T Function(dynamic) byIndex<T extends Enum>(List<T> values);
}
// Shortcuts on List<T extends Enum>
extension EnumValuesParsing<T extends Enum> on List<T> {
T Function(dynamic) get parser; // byName
T Function(dynamic) parserWithFallback(T fallback);
T Function(dynamic) get parserCaseInsensitive;
T Function(dynamic) get parserByIndex;
}
Utilities
// JSON (String)
extension TextJsonX on String {
Object? tryDecode(); // returns jsonDecode or original String
dynamic decode(); // jsonDecode (throws on error)
}
// Numbers (String)
extension NumParsingTextX on String {
num toNum(); num? tryToNum();
int toInt(); int? tryToInt();
double toDouble(); double? tryToDouble();
// Localized via intl
num toNumFormatted(String format, String? locale);
num? tryToNumFormatted(String format, String? locale);
int toIntFormatted(String format, String? locale);
int? tryToIntFormatted(String format, String? locale);
double toDoubleFormatted(String format, String? locale);
double? tryToDoubleFormatted(String format, String? locale);
}
// Dates (String)
extension DateParsingTextX on String {
DateTime toDateTime(); DateTime? tryToDateTime();
DateTime toDateFormatted(String format, String? locale, {bool utc=false});
DateTime? tryToDateFormatted(String format, String? locale, {bool utc=false});
DateTime toDateAutoFormat({String? locale, bool useCurrentLocale=false, bool utc=false});
DateTime? tryToDateAutoFormat({String? locale, bool useCurrentLocale=false, bool utc=false});
}
// URIs (String)
extension UriParsingX on String {
bool get isValidPhoneNumber;
bool get isEmailAddress;
Uri get toPhoneUri; // tel:
Uri get toMailUri; // mailto:
Uri get toUri; // Uri.parse(this)
}
// Pretty JSON (Map/Iterable/Object)
extension PrettyJsonMap<K, V> on Map<K, V> {
Map<String, dynamic> get encodableCopy;
String get encodedJsonText; // pretty JSON
}
extension PrettyJsonIterable on Iterable<dynamic> {
List<dynamic> get encodableList;
String get encodedJson;
String encodedJsonWithIndent([String indent = ' ']);
}
extension PrettyJsonObject on Object? {
String encode({Object? Function(dynamic object)? toEncodable});
}
// Booleans (Object?)
extension BoolParsingX on Object? {
bool get asBool; // deterministic truthiness
}
Results — ConversionResult<T>
class ConversionResult<T> {
// Constructors
factory ConversionResult.success(T value);
factory ConversionResult.failure(ConversionException error);
// State
bool get isSuccess;
bool get isFailure;
// Access
T get value; // throws if failure
T? get valueOrNull; // null if failure
T valueOr(T defaultValue);
ConversionException? get error;
// Combinators
ConversionResult<R> map<R>(R Function(T value) transform);
ConversionResult<R> flatMap<R>(ConversionResult<R> Function(T value) next);
// Fold
R fold<R>({required R Function(T value) onSuccess,
required R Function(ConversionException error) onFailure});
}
Exceptions — ConversionException
try {
final n = ConvertObject.toInt('oops');
} on ConversionException catch (e) {
e.toString(); // concise, filtered context
e.fullReport(); // verbose JSON context + stack trace (for logs)
}
Behavior highlights (quick)
// Booleans: truthy('true','1','yes','y','on','ok','t'), falsy('false','0','no','n','off','f')
// Numbers: accepts "1 234.56", "1,234", "(2,500)" → -2500, underscores/spaces ignored
// Dates: auto-detect supports ISO/RFC3339, HTTP-date (GMT), Unix epoch, slashed by locale,
// compact yyyyMMdd[HHmm[ss]], long names via intl, time-only → today
// URIs: plain emails → mailto:, phones → tel:, http/https validation for host/path
// Collections: JSON strings auto-decoded when converting to List/Set/Map
// Generic: toType<T>() routes special types (bool,int,double,num,BigInt,String,DateTime,Uri)
Libraries
- convert_object
- A comprehensive type conversion library for Dart.