Search code examples
flutterserializationjson-serialization

How to serialize a class containing a collection of an abstract class?


Lets take a look at a simple class hierarchy consisting of three classes:

  1. An abstract base class:

    abstract class BaseClass {
      String name;
    
      BaseClass(this.name);
    }
    
  2. A few classes derived from the abstract base class.

    @JsonSerializable()
    class ConcreteClass extends BaseClass {
      int someValue;
    
      ConcreteClass(this.someValue, String name) : super(name);
    
      factory ConcreteClass.fromJson(Map<String, dynamic> json) => _$ConcretClassFromJson(json);
    
      Map<String, dynamic> toJson() => _$ConcreteClassToJson(this);
    }
    
  3. And finally a main class that stores all the concrete classes in a collection. Here's an example how it could look like:

    @JsonSerializable()
    class DataJuggler {
      Set<BaseClass> allTheDataInTheWorld = Set<BaseClass>();
    
      DataJuggler();
    
      factory DataJuggler.fromJson(Map<String, dynamic> json) => _$DataJugglerFromJson(json);
    
      Map<String, dynamic> toJson() => _$DataJugglerToJson(this);
    }
    

When launching the build_runner to generate the json serialization code, it fails with:

[SEVERE] json_serializable:json_serializable on lib/what_an_awesome_app/data_juggler.dart:

Could not generate `fromJson` code for `allTheDataInTheWorld` because of type `BaseClass`.
package:/totally_awesome/what_an_awesome_app/data_juggler.dart:12:25
   ╷
12 │   Set<BaseClass> allTheDataInTheWorld = Set<BaseClass>();
   ╵

Now the question is, what's wrong here? Or better: How can you get the json serialization code generated for the DataJuggler class? Your advise is very much welcome. Thank you.


Solution

  • You need to manually write down a bit of boilerplate code: https://github.com/google/json_serializable.dart/issues/145, https://github.com/google/json_serializable.dart/issues/371, and Extend with fromJson in dart.

    Notice that your BaseClass is lacking a fromJson currently, so DataJuggler definitely has no way of generating a fromJson!