I'm failing to cast a Map<String, dynamic> into a Map<String, Map<String, String>. What is the best way to do this?
Note that I'm using the advanced analysis options in my analysis_options.yaml:
analyzer:
  enable-experiment:
    - extension-methods
  strong-mode:
    implicit-casts: false
    implicit-dynamic: false
I tried
var de = Map<String, Map<String, String>>.from((json.decode(await rootBundle.loadString('lang/de.json'))) as Map<String, dynamic>);
and
var de = (json.decode(await rootBundle.loadString('lang/de.json')) as Map<String, dynamic>).cast<String, Map<String, String>>();
and
var de = Map.castFrom<String, dynamic, String, Map<String, String>>((json.decode(await rootBundle.loadString('lang/de.json'))) as Map<String, dynamic>);
All attempts raised the following runtime error: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Map<String, String>' in type cast
What is the best way to this? I think this can be done by iterating through the map but if these are very large, this is an expensive operation. Is there any way to cast them without iterating?
I don't believe there is a way to cast to the appropriate type when dealing with nested data like this.
There was a similar discussion here about casting nested lists: https://github.com/dart-lang/language/issues/1574
I think iterating over the data in some fashion is the only thing you can do in this situation.
One possible solution:
final data = await rootBundle.loadString('lang/de.json');
final Map<String, Map<String, String>> de = {
  for (final entry in (json.decode(data) as Map).entries)
    entry.key as String: {
      for (final e in (entry.value as Map).entries)
        e.key as String: e.value as String,
    },
};
Since dart 3.3, one potential option that would have less overhead would be to create extension type wrappers on the json object.
for example:
import 'dart:convert';
extension type LanguageMap(Map<String, dynamic> json) {
  TranslationMap? operator [](String s) => json[s] as TranslationMap?;
}
extension type TranslationMap(Map<String, dynamic> json) {
  String? operator [](String s) => json[s] as String?;
}
void main() {
  Map<String, dynamic> json = jsonDecode(
          '{ "english": {"hello": "Hello"}, "spanish": {"hello": "Hola"} }')
      as Map<String, dynamic>;
  final lang = LanguageMap(json);
  final String? result = lang['spanish']?['hello'];
  print(result); // Hola
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With