I have data from Firebase that looks something like this:
{
"foo": {
1: true,
2: false
},
"bar": {
3: true,
4: false
}
}
If I'm not mistaken, this should be a Map<String, Map<int, bool>>. I'm trying to use this function to safely cast it:
T castWithDefaultValue<T> (val, T defaultValue) => val is T ? val : defaultValue;
var castData = castWithDefaultValue<Map<String, Map<int, bool>>>(dataFromFirebase, {});
But it fails, always returning the default value. The only types I can get to work for either the key or the value are Object? and dynamic, but I want more type safety. How do I get it to what I want it to be?
CodePudding user response:
When I have a snapshot with just string values, getting them is a two-step process:
var data = snapshot.val() as Map<String,dynamic>;
var values = Map<String, String>.from(data);
The first line is a regular cast, while the second line is a data conversion. Also see: Difference between List<String>.from() and as List<String> in Dart
I'm not sure if your conversion can be done for the entire object in one go, but if it can it'd be something like:
Map<String, Map<int, bool>>.from(dataFromFirebase)
That seems to work here at least: https://dartpad.dev/9dad7a0e39add2c690b3b54afe284005
CodePudding user response:
I don't think you can cast a nested data structure like this. See this discussion for more info.
The best I think you can do is deep copy the data structure into a new collection and cast each part as you are copying. In this case you could do something like:
void main() {
// intentionally removing type data for example
dynamic data = <dynamic, dynamic>{
"foo": <dynamic, dynamic>{1: true, 2: false},
"bar": <dynamic, dynamic>{3: true, 4: false},
};
final deepCopy = {
for (final entry in data.entries)
entry.key as String: {
for (final subEntry in entry.value.entries)
subEntry.key as int: subEntry.value as bool,
},
};
print(deepCopy);
print(deepCopy.runtimeType);
}
