Flutter realtime database onValue parsing

600

Just need to add a null check. like this;

.....
.onValue
.map((event) {
    List<ListsModel> _offers = <ListsModel>[];
    if(event.snapshot.value != null) {
        final _resultList =
          Map<String, dynamic>.from(e.snapshot.value as LinkedHashMap);
        for (var key in _resultList.keys) {
        Map<dynamic, dynamic> map = Map.from(_resultList[key]);
        ListsModel listsModel = ListsModel.fromMap(map);
        _offers.add(listModel);
    }
}
.....
Share:
600
Michael m
Author by

Michael m

Updated on December 28, 2022

Comments

  • Michael m
    Michael m over 1 year

    I'm experimenting with NoSQL (firebase realtime database) for the first time and I'm having some issues structuring and parsing data in a Flutter app. At first I had a simple "Person" model with some attributes and all was fine but then I had to introduce an ID as node and nesting the other attributes in order to perform CRUD operations and now I'm not able to parse my "updated" 'Person' model anymore. I don't know if that's ok but, for simplicity (I know it's not a proper ID), I decided that my ID ('personName' attribute) is the name of the person so the current structure on DB is:

    realtime db to object

    I'm using freezed package and PersonDto looks like this (domains methods omitted):

    @freezed
    class PersonDto with _$PersonDto  {
      const PersonDto ._();
    
      const factory PersonDto ({
        required String personName,
        required int age,
        required String genre,
        required double height,
        required String hobby,
        required double weight,
      }) = _PersonDto ;
    
      factory PersonDto.fromJson(Map<String, dynamic> json) =>
          _$PersonDto FromJson(json);
    

    In the repository there's a method responsible to receive, parse and stream data from firebase. My problem is basically that I'm not able to generate a 'Person' model using the key of the node as an attribute for the 'name'. This is the closest I get :

    Stream<Either<PersonFailure, List<Person>>> watchAll() async* {
    yield* _firebaseDatabase
        .reference()
        .child('persons')
        .onValue
        .map((event) {
      return right<PersonFailure, List<Person>>(
          (event.snapshot.value as LinkedHashMap).values.map((personMap) {
        final json = Map<String, dynamic>.from(personMap as LinkedHashMap);
    //
    //this snippet works. I'm able to generate a proper 'Person' model but like this 
    //there's no way to retrieve the key from event.snapshot.value
    //
        json.addAll({
          'personName': 'NAME OF THE PERSON',
        });
       return PersonDto.fromJson(json).toDomain();     
      }).toList());
    }).onErrorReturnWith((e) {
      print('WATCH ERROR ${e.toString()}');
      return left(const PersonFailure.unexpected());
    });
    }
    

    Should be something like this, which likewise doesn't work, unfortunately:

    yield* _firebaseDatabase
        .reference()
        .child('persons')
        .onValue
        .map((event) {
      (event.snapshot as LinkedHashMap).map((key, value) {
        final personName = key;
        final json = value as Map<String,dynamic>;
        json.addAll({'personName':personName});
        //
        //error: The return type 'Person' isn't a 'MapEntry<_, _>', as required by the closure's context.
        //
        return PersonDto.fromJson(json).toDomain();
      });
    });