Home > Back-end >  Model a server response with Class
Model a server response with Class

Time:09-24

I have a flutter application, which uses some server APIs.

When there is a successful response from the server, it would return json back:

{"success": true, "message": "success", "data": {"id": "21EE"} }

However, when there is failure, it would return:

{"success": false, "message": "failure"}

For more strict-typed use of flutter, I try to model the response.

Here is my try:

class ServerResponse {
  final bool success;
  final String message;

  ServerResponse({
    required this.success,
    required this.message,
  });
}



class _AuthAutenticationData {
  final String id;

  _AuthAutenticationData({
    required this.id,
  });
}

class AutoAuthenticateResponse extends ServerResponse {
  final _AuthAutenticationData? data;

  AutoAuthenticateResponse({
    required success,
    required message,
    this.data,
  }) : super(success: success, message: message);
}

Now, I have a function which calls a specific API:

Future<void> autoAuth() async {
  final url = Uri.parse('${this._baseURL.toString()}/auto-auth');

  try {
    final response = await http.post(url, headers: {
      'Authorization': 'SXXX',
    });
    print(response.body);
    final AutoAuthenticateResponse responseBody = json.decode(response.body);

    if (responseBody.success) {
      return setUser(new User(id: responseBody.data!.id));
    }

    setUser(null);
  } catch (error) {
    print(error);
    setUser(null);
  }
}

Some code is irrelevant, but bottom line is that I receive the following error in the line: final AutoAuthenticateResponse responseBody = json.decode(response.body);:

I/flutter (14139): type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'AutoAuthenticateResponse'

I guess my solution is bad. Any advice how to fix it?

CodePudding user response:

Use this link to generate models for your response

CodePudding user response:

Well, you can use nullsafety feature for this. Since it's only if when the failure the data is not being returned.

{"success": true, "message": "success", "data": {"id": "21EE"} }

you can use this : https://meruya-techhnology.github.io/json-to-dart/

Then the result will be a 2 class

class YourClass {
  final bool success;
  final String message;
  final Data? data;

  YourClass({this.success, this.message, this.data});

  factory YourClass.fromJson(Map<String, dynamic> json) => YourClass(
    success : json['success'],
    message : json['message'],
    data : json['data'] != null ? new Data.fromJson(json['data']) : null;
  );

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['success'] = this.success;
    data['message'] = this.message;
    if (this.data != null) {
      data['data'] = this.data.toJson();
    }
    return data;
  }
}

And

class Data {
  String id;

  Data({this.id});

  Data.fromJson(Map<String, dynamic> json) {
    id = json['id'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['id'] = this.id;
    return data;
  }
}

Then you can use it like this :

Future<void> autoAuth() async {
  final url = Uri.parse('${this._baseURL.toString()}/auto-auth');

  try {
    final response = await http.post(url, headers: {
      'Authorization': 'SXXX',
    });
    debugPrint(response.body);
    final responseBody = YourClass.fromJson(response.body)
    if (responseBody.success) {
      return setUser(new User(id: responseBody.data!.id));
    }
    setUser(null);
  } catch (error) {
    print(error);
    setUser(null);
  }
}

another advice is use debugPrint instead of print, here you can read more : https://medium.com/flutter-community/debugprint-and-the-power-of-hiding-and-customizing-your-logs-in-dart-86881df05929

  • Related