toMapStringDynamic static method

  1. @useResult
Map<String, dynamic>? toMapStringDynamic(
  1. dynamic json, {
  2. bool ensureUniqueKey = false,
  3. bool throwOnDuplicate = false,
})

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:

  • throwOnDuplicate true: throws ArgumentError on the first collision so callers can detect lossy input instead of dropping data silently.
  • ensureUniqueKey true: keeps the first colliding value.
  • both false (default): the last colliding value wins (matches Dart's Map.map overwrite 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;
}