-1

Within my client I have a class, e.g., ClassA that contains a property List<ClassB>.

My goal is to save the object ClassA within Firestore. Also I want the List<ClassB> property saved into Firestore as a Map instead of an Array (also be able to save it as a List<Object> within the client).

Since I want to use the json_serializable library is there a way to specify for a given class' property how to get serialized/deserialized and choose what kind of a key should be used for the Firestore Map?

Georgios
  • 861
  • 2
  • 12
  • 30
  • Why not just convert the List into a Map, and provide that to Firestore? – Doug Stevenson Jul 19 '20 at 17:09
  • @DougStevenson This is what I am trying to do, but I am not sure how to with the json_serializable. I want to keep the List structure in my client though. – Georgios Jul 19 '20 at 17:12
  • You don't have to abandon the list. Just use it to compose a map for the purpose of writing to Firestore. – Doug Stevenson Jul 19 '20 at 17:14
  • @DougStevenson right, so we are talking about the same thing :) My question is, if it is possible to do this semi-automatically using the library mentioned above instead of writing this manually. – Georgios Jul 19 '20 at 17:21
  • As far as I can see, that library deals with JSON, not other objects Dart objects. Firestore doesn't deal with JSON, it deals with Dart objects. – Doug Stevenson Jul 19 '20 at 17:50

2 Answers2

0

In order to convert a List to a Map you should not need to convert the object to JSON and then back.

You can use Map.fromIterable() or collection-for to convert a List to Map. See this other SO answer

Jose V
  • 1,356
  • 1
  • 4
  • 12
  • You are right in this case. Although this is not what I was trying to explain. I was talking about the different datastructures that I want to use in my database and my client. For this case I need a `toMap/fromMap` or `toJson/fromJson`. I did find the solution. It is also posted here now. – Georgios Jul 20 '20 at 16:52
0

I did find the answer to my question.

So in order to use the json_serializable for the remaining ClassA properties I have to use the @JsonKey annotation for the property List<ClassB>. By doing this, I can then use custom fromJson/toJson methods. In this methods I can transform myList to an appropriate Map for Firestore.

This is how I have to use it:

@JsonKey( fromJson: _firestoreMapToList, toJson: _listToFirestoreMap)
final List<ClassB> myList;

The methods _firestoreMapToList and _listToFirestoreMap will "override" the automatically generated methods of the classA.g.dart file, which is also automatically generated when using the json_serializable library and entering this flutter pub run build_runner watch in the terminal.

This is how the methods exactly look like:

static List<ClassB> _firestoreMapToList(Map<String, dynamic> firestoreMap) {
 if (firestoreMap != null) {
  return List<ClassB>.from(firestoreMap?.entries
      ?.map((e) => ClassB.fromJson(e.value))
      ?.toList());
 }
 return null;
}


static Map<String, Map<String, dynamic>> _listToFirestoreMap(List<ClassB> list) {
 if (list != null) {
  return Map<String, Map<String, dynamic>>.from(list?.asMap()?.map(
      (key, classB) => MapEntry(
          classB.firebaseId,
          classB.toJson())))
    ..removeWhere((key, value) => key == null); // remove map entries with null as key
 }
 return null;
}
Georgios
  • 861
  • 2
  • 12
  • 30