0

I have two classes: BaseClass (BaseResponse) and DerivedClass (LoginResponse). I am de-serializing them using the fromJson method.

I want to understand how can I call the fromJson method for the base class.

class BaseResponse { 
  int responseCode;
  String responseMessage;

  BaseResponse.fromJson(Map<String, dynamic> input)
      : responseCode = input["ResponseCode"],        
        responseMessage = input["ResponseMessage"];
}
class LoginResponse extends BaseResponse {
    String authenticationToken;
    
    LoginResponse.fromJson(Map<String, dynamic> input) 
      : authenticationToken = input["AuthenticationToken"];

}

LoginResponse.fromJson(Map<String, dynamic> input) gives me an error saying: The class 'BaseResponse' doesn't have an unnamed constructor.

Any help is appreciated.

Thanks.

Tushar
  • 1,242
  • 1
  • 8
  • 19

3 Answers3

2

Define constructors in base class.

BaseResponse({required this.responseCode, required this.responseMessage});

and in derived class

LoginResponse(
      {required this.authenticationToken,
      required int responseCode,
      required String responseMessage})
      : super(responseCode: responseCode, responseMessage: responseMessage);

Add LoginResponse.fromJson as factory and use constructor of LoginResponse.

factory LoginResponse.fromJson(Map<String, dynamic> input) => LoginResponse(
          authenticationToken: input['AuthenticationToken'],
          responseCode: input['ResponseCode'],
          responseMessage: input['ResponseMessage']);

Classes should be like this:

class BaseResponse {
  int responseCode;
  String responseMessage;

  BaseResponse({required this.responseCode, required this.responseMessage});

  BaseResponse.fromJson(Map<String, dynamic> input)
      : responseCode = input["ResponseCode"],
        responseMessage = input["ResponseMessage"];
}

class LoginResponse extends BaseResponse {
  String authenticationToken;

  LoginResponse(
      {required this.authenticationToken,
      required int responseCode,
      required String responseMessage})
      : super(responseCode: responseCode, responseMessage: responseMessage);

  factory LoginResponse.fromJson(Map<String, dynamic> input) => LoginResponse(
      authenticationToken: input['AuthenticationToken'],
      responseCode: input['ResponseCode'],
      responseMessage: input['ResponseMessage']);
}
milkyWay
  • 106
  • 1
  • 4
0

I wouldn't make a .fromJson for the BaseResponse unless you absolutely need it for some reason.

A better approach in my opinion would be declaring final variables in the base class and asserting expressions there, and only implementing the model or any sort in the derived classes:

class BaseResponse { 
  final int responseCode;
  final String responseMessage;

  BaseResponse({@required this.responseCode, @required this.responseMessage)
  : assert(<expression>);
}

class LoginResponse extends BaseResponse {
  final String authenticationToken;
  final int code;
  final String message;
   
  LoginResponse({
    this.authenticationToken,
    this.code,
    this.message,
  }) : super(code: code, message: message)

  LoginResponse.fromJson(Map<String, dynamic> input) {
    return LoginResponse(
    authenticationToken: input['token'],
    code: input['code'],
    message: input['message'],
    );
  }

}
baselsader
  • 424
  • 2
  • 4
  • 16
  • Thanks for the reply. Well, I am not sure why should we re-declare the variables in the deriving class. I implemented the function fromJson in base, so that I don't have to worry about their implementation. I just declare new fields in the derived class, use them, serialize and de-serialize them and leave the remaining job to the base class. Any thoughts. I am from C# background, so please spare me my limited knowledge with Dart / Flutter. – Tushar Oct 14 '20 at 11:42
  • Sure thing, now I understand what you mean by base and derived class, the answer might need a bit of tweaking. Have you considered having a Base Class with declarations but no implementations (as in the answer), an extension (BaseClassModel) with the implementations as described above, and then any number of derived class (such as LoginResponse) which would extend the model class, thus enabling you to control any updates of BaseClass , while keeping the core clean and each derived class's model unique. This answer is based upon the clean architecture approach in Flutter. – baselsader Oct 15 '20 at 08:50
-1

Post Data by BaseResponse use url,parameter json body:

Future<dynamic> postData(String _url, dynamic _body, {@required latlng = null}) async {
    BaseResponse responseJson;
    try {
      Uri url = Uri.parse(_url);
      latlng = latlng ?? '93.2548,23.5987';
      var headers = {"latLng": "$latlng", "Content-Type": "application/json", 'Authorization': 'Bearer ${CtsSharedPreferences.getString('token')}'};
      final response = await post(url, headers: headers, body: _body);
      responseJson = _returnResponse(response);
    } on SocketException {
      throw FetchDataException('No Internet connection');
    }
    return responseJson;
  }
Rahamat
  • 49
  • 2
  • 6