Dart / Flutter: Mapping json to object having a base class using fromJson in base object

1.3k views Asked by At

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.

3

There are 3 answers

2
baselsader On

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

}
0
milkyWay On

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']);
}
0
Rahamat On

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