2

Say one has an abstract Car class with a derived Cabrio class.

From a REST api he recieves a JSON with data

abstract class Car {
  int id;
  String name;
  String description;

  Car({
    this.id,
    this.name,
    this.description,
  });

  factory Car.fromJson(Map<String, dynamic> json, String type) {
    Car car;
    if (type == 'cabrio') car = Cabrio.fromJson(json);
    // other possible if-statements
    car.id = int.parse(json['id']);
    car.name = json['name'];
    car.description = json['description'];
    return car;
  }


class Cabrio extends Car {
  String roofMaterial;
  String someOtherProp;

  Cabrio({
    id,
    name,
    this.roofMaterial,
    this.someOtherProp
  }) : super(
            id: id,
            name: name,
            description: description);

  factory Cabrio.fromJson(Map<String, dynamic> json) =>
    Cabrio(
        roofMaterial: json['roof_material'],
        someOtherProp: json['some_other_prop']
    );
}

dynamic dyn = jsonDecode(response.body);
Cabrio cabrio = Car.fromJson(dyn[0], 'cabrio');
cabrio.roofMaterial // null  
cabrio.someOtherProp // null 
return cabrio;

Why is cabrio.roofMaterial or cabrio.someOtherProp null ?

Why I am taking this approach

I didn't like seeing for example

id: json['id'] 

in all derived classes. This approach is to prevent such redundancy

What I know

  • according to the debugger, the properties of the derived class Cabrio are set correctly by the json values in it's fromJson
  • when inspecting the car object at car.name = json['name'] the derived class' properties (like cabrio.roofMaterial) are already null

What I consider to be a problem at

if (type == 'cabrio') car = Cabrio.fromJson(json, type);

I am 'pushing' a cabrio object into a Car object (which has less properties than Cabrio). But that should not be wrong since it's just a parent class type

CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
MwBakker
  • 498
  • 5
  • 18
  • Which version of flutter are you using? Can you post a working example? You can paste your code on to dartpad.dev and try running it there. The current code does not compile with a nullable version of dart. Parameters to the constructor of Car should be `required`, Cabrio's params should be typed, and so on.. – Amarghosh Nov 23 '22 at 23:56
  • 1
    Which version of flutter are you using? - 2.8.2 <> Can you post a working example? - I can consider this but not immediatly <> The current code does not compile with a nullable version of dart - correct for I do not use that <> Parameters to the constructor of `Car` should be required, `Cabrio's` params should be typed - this does not affect the problem in my question – MwBakker Nov 24 '22 at 00:16

1 Answers1

1

What you're needing in this example is an explicit type cast after you call Car.fromJson(...) to ensure that the type you're dealing with is Cabrio which has the extra fields rather than an instance of Car

final cabrio = Car.fromJson(json, 'cabrio') as Cabrio;

I spent some time to update your code to a newer version of Dart with the changes required to ensure that these fields were no longer null

https://gist.github.com/MarkOSullivan94/60ce6625538e16f373c5c1d6254952e9

Mark O'Sullivan
  • 10,138
  • 6
  • 39
  • 60