13

How can we create object of generic types in dart?

For my use case, each of my api responses are wrapped as ApiResponse class. For login api response, I get a json object such as

{
    "data": {
        "email": "[email protected]",
        "name": "A"
    },
    "message": "Successful",
    "status": true
}

So to parse these responses, I created classes as below, but they throw compile time error stating that The method 'fromJson' isn't defined for the class 'Type'. :

class ApiResponse<T extends BaseResponse> {
  bool status;
  String message;
  T data;

  ApiResponse.fromJson(Map<String, dynamic> json) {
    status = json['status'];
    message = json['message'];
    data = T.fromJson(json['data']);  // <<<------- here is the compile time error
  }
}

abstract class BaseResponse {
  BaseResponse.fromJson(Map<String, dynamic> json);
}

class Login extends BaseResponse {
  String name, email;

  Login.fromJson(Map<String, dynamic> json) : super.fromJson(json) {
    name = json['name'];
    email = json['email'];
  }
}

// and I want to use it like below
usage() {
  ApiResponse<Login> a = ApiResponse.fromJson({});
  String name = a.data.name;
}

Can anyone help me fix the error?

5
  • Umm, usually you don't call methods on a type right? I wonder if your intent is to do data = data.fromJson(json['data']) Commented Jan 10, 2020 at 8:34
  • We get this error if we use data = data.fromJson(json['data']) :: main.dart:9:17: Error: The method 'fromJson' isn't defined for the class 'BaseResponse'. - 'BaseResponse' is from 'main.dart'. data = data.fromJson(json['data']); ^^^^^^^^ Error: Compilation failed. Commented Apr 8, 2020 at 10:13
  • @JainamJhaveri did you solve this? please help me by answering the question Commented Oct 21, 2020 at 15:23
  • Haven't managed to solve this Commented Oct 21, 2020 at 15:38
  • You can't inherit constructors in Dart. You can only inherit instance members. Commented Jun 14, 2021 at 19:18

2 Answers 2

3

ok let's add a little hack to manage your use case:

  • let say that you have two responses Login and Error both of Type BaseResponse
abstract class BaseResponse {}

class Login extends BaseResponse {
  Login.fromJson(Map<String, dynamic> json) {}
}

class Error extends BaseResponse {
  Error.fromJson(Map<String, dynamic> json) {}
} 
  • the trick is that you will decide the type of BaseResponse at ApiResponse constructor like this
class ApiResponse<T extends BaseResponse> {
  T data;

  ApiResponse.fromJson(Map<String, dynamic> json) {
    data = _getProperDataValue<T>(json['data']);
  }

  static E _getProperDataValue<E extends BaseResponse>(
      Map<String, dynamic> jsonData) {
    switch (E) {
      case Login:
        return Login.fromJson(jsonData) as E;
      case Error:
        return Error.fromJson(jsonData) as E;
      default:
        throw UnsupportedError('Not Supported Type');
    }
  }
}
  • both responses will work
void main(List<String> arguments) {
  final loginRes = ApiResponse<Login>.fromJson(<String, dynamic>{
    'data': <String, dynamic>{},
  });
 final errorRes = ApiResponse<Error>.fromJson(<String, dynamic>{
    'data': <String, dynamic>{},
  });
}
 
Sign up to request clarification or add additional context in comments.

Comments

0

You need to cast T as BaseResponse :

data = (T as BaseResponse).fromJson(json['data']);

4 Comments

We get following error:: ``` main.dart:9:32: Error: The method 'fromJson' isn't defined for the class 'BaseResponse'. - 'BaseResponse' is from 'main.dart'. data = (T as BaseResponse).fromJson(json['data']); ^^^^^^^^ Error: Compilation failed. ```
Can you try to use factory keyword before BaseResponse.fromJson(Map<String, dynamic> json);?
@AugustinR using factory will also not work

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.