Home > OS >  How do you cast data from Firebase to a fully typed Map?
How do you cast data from Firebase to a fully typed Map?

Time:01-05

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);
}
  •  Tags:  
  • Related