Home > Net >  Having trouble creating generic Dart constructor for Json conversion
Having trouble creating generic Dart constructor for Json conversion

Time:03-21

To all Dart gurus: I'm trying to implement a generic networking layer in Dart that converts REST service response to a specified model class:

// The idea is to make a network call and get a deserialized model as a response:

final token =
        await _authNetworkService.execute<AccessTokenResponse>(request);

Here is the implementation:

// Model interface
abstract class JsonConvertible {
  Map<String, dynamic> toJson();
  JsonConvertible.fromJson(Map<String, dynamic> json);
}

// Model
class AccessTokenResponse extends JsonConvertible {
  String? accessToken;

  @override
  Map<String, dynamic> toJson() {
    return {};
  }

  @override
  AccessTokenResponse.fromJson(Map<String, dynamic> json)
      : super.fromJson(json) {
    accessToken = json['access_token'];
  }
}

// Network response class
class NetworkResponse<Model> {
  Model data;
  
  NetworkResponse.ok(this.data);
}

// Class to create a valid network service request
class NetworkRequest {
}

// Class that performs all network calls
class NetworkService {
  Future<NetworkResponse<M>> execute<M extends JsonConvertible>(NetworkRequest request) async {
    // For simplicity replaced all DIO calls with static data:
    final response = {'data': {'access_token': 'XXX'}};

    return NetworkResponse.ok(M.fromJson(response['data'])); //<- Fails here with error: Method 'fromJson' isn't defined for the type 'Type'...
  }
}

DartPad: https://dartpad.dev/?id=9a29a7e49a084e69fd1d8078d5f2b977

How can I achieve expected behavior?

CodePudding user response:

one way you can solve this is by passing the fromJson constructor as an argument to the execute function but this will add another step for every time execute is called

// Class that performs all network calls
class NetworkService {
  Future<NetworkResponse<M>> execute<M extends JsonConvertible>(NetworkRequest request,M Function(Map<String, dynamic>) parser ) async {
    // For simplicity replaced all DIO calls with static data:
    final response = {'data': {'access_token': 'XXX'}};

    return NetworkResponse.ok( parser(response['data']!)); //<- Fails here with error: Method 'fromJson' isn't defined for the type 'Type'...
  }
}

and this is how you would call the execute function

 final token =
        await _authNetworkService.execute<AccessTokenResponse>(request,AccessTokenResponse.fromJson);
  • Related