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:

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();
});
});
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);
}
}
.....
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