toMapStringDynamic static method
Returns json as a Map<String, dynamic>, or null if conversion is
not possible.
All keys are converted to String via toString(). Two distinct source
keys can collapse to the same string (e.g. the int 1 and the String
'1' both become '1'); without handling, one value is silently lost.
The collision policy is explicit:
throwOnDuplicatetrue: throws ArgumentError on the first collision so callers can detect lossy input instead of dropping data silently.ensureUniqueKeytrue: keeps the first colliding value.- both
false(default): the last colliding value wins (matches Dart'sMap.mapoverwrite behavior).
throwOnDuplicate takes precedence over ensureUniqueKey.
Implementation
@useResult
static Map<String, dynamic>? toMapStringDynamic(
dynamic json, {
bool ensureUniqueKey = false,
bool throwOnDuplicate = false,
}) {
if (json == null) {
return null;
}
if (json is Map<String, dynamic>) {
return json;
}
if (json is Map<dynamic, dynamic>) {
final Map<String, dynamic> result = <String, dynamic>{};
for (final MapEntry<dynamic, dynamic> entry in json.entries) {
final String key = entry.key.toString();
// Detect string-key collisions before overwriting so any data loss is a
// deliberate, caller-chosen outcome rather than a silent surprise.
if (result.containsKey(key)) {
if (throwOnDuplicate) {
throw ArgumentError(
'Duplicate key after toString() conversion: "$key" '
'(from ${entry.key.runtimeType})',
);
}
// Keep the first occurrence; skip this colliding value.
if (ensureUniqueKey) {
continue;
}
// Otherwise fall through and let the last value win.
}
result[key] = entry.value;
}
return result;
}
return null;
}