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.

3 Answers 3

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']);
}
Sign up to request clarification or add additional context in comments.

Comments

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'],
    );
  }

}

2 Comments

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.
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.
-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;
  }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.