flutter dart JsonSerializable with inherited class
Asked Answered
B

4

14

I have the following two classes where one is extending from the other like this :

@JsonSerializable(nullable: true)
class Response {
  final String responseCode;
  final String responseMessage;
  final String errorLog;
  Response({this.errorLog, this.responseCode, this.responseMessage});
  factory Response.fromJson(Map<String, dynamic> json) =>
      _$ResponseFromJson(json);
}

.........................................................

 @JsonSerializable(nullable: false)
class Verify extends Response {
  Data data;
  Verify({
    this.data,
  });
  factory Verify.fromJson(Map<String, dynamic> json) => _$VerifyFromJson(json);
  Map<String, dynamic> toJson() => _$VerifyToJson(this);
}

and whenever I'm trying to read response class properties from Verify class, it's always null.

so please how to achieve this?

Boarish answered 2/6, 2020 at 4:43 Comment(1)
datacontractjsonserializer is a .NET component that makes it possible to directly serialize .NET objects into JSON data. Since you are using flutter and dart and not c# or any other .Net language, I removed the tag.Leftward
B
16

this one I have solved by passing the parameters to super in verify class constructor like this

@JsonSerializable()
class VerifyResponse extends Response {
  Data data;

  VerifyResponse({
    this.data,
    String responseCode,
    String responseMessage,
  }) : super(responseCode: responseCode, responseMessage: responseMessage);

  factory VerifyResponse.fromJson(Map<String, dynamic> json) =>
      _$VerifyResponseFromJson(json);

  Map<String, dynamic> toJson() => _$VerifyResponseToJson(this);
}

and for the response class it remains the same

@JsonSerializable()
class Response {
  final String responseCode;
  final String responseMessage;

  Response({this.responseCode, this.responseMessage});

  factory Response.fromJson(Map<String, dynamic> json) =>
      _$ResponseFromJson(json);
}

it's a bit annoying but it's what it's.

Boarish answered 19/8, 2020 at 7:53 Comment(0)
G
2

You should remove 'final' keyword from Response Class

@JsonSerializable(nullable: true)
    class Response {
      String responseCode;
      String responseMessage;
      String errorLog;
      Response({this.errorLog, this.responseCode, this.responseMessage});
      factory Response.fromJson(Map<String, dynamic> json) =>
           _$ResponseFromJson(json);
}
Grimaldi answered 18/3, 2021 at 8:23 Comment(3)
Removing "final" keyword in base class members fixed it for me. Thanks!Doone
why? what would be the point of removing final. it only means that this value will be taken from the contractureBoarish
It does not make sense to remove final if the fields are intended to be immutable.Pleistocene
R
0

It worked by adding super(); explicitly to the child class's constructor.

@JsonSerializable()
class VerifyResponse extends Response {
  Data data;

  VerifyResponse({
    this.data,
    String responseCode,
    String responseMessage,
    //No need to list all parent class properties
    }) : super();

  factory VerifyResponse.fromJson(Map<String, dynamic> json) =>
      _$VerifyResponseFromJson(json);

  Map<String, dynamic> toJson() => _$VerifyResponseToJson(this);
}
Respecting answered 1/4, 2021 at 11:13 Comment(0)
S
0

I would like to extend the answer as there are a couple more gotchas.

You can't use the super.responseCode syntax in the constructor:

Incorrect

  VerifyResponse({
    this.data,
    super.responseCode,
    super.responseMessage,
  })

Correct

  VerifyResponse({
    this.data,
    String responseCode,
    String responseMessage,
  }) : super(responseCode: responseCode, responseMessage: responseMessage);

You also have to define the type in the constructor, otherwise they get passed to the super constructor as dynamic:

Incorrect

  VerifyResponse({
    required this.data,
    required responseCode,
    required responseMessage,
  }) : super(responseCode: responseCode, responseMessage: responseMessage);

Correct

  VerifyResponse({
    required this.data,
    required String responseCode,
    required String responseMessage,
  }) : super(responseCode: responseCode, responseMessage: responseMessage);
Speciation answered 17/5, 2023 at 7:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.