Skip to content

Response Parser makes it easier to parse data and error response from server.

License

Notifications You must be signed in to change notification settings

qyre-ab/response_parser

Repository files navigation

Response Parser makes it easier to parse data and error responses from the server.

Getting started

Do you want to write pretty functions like this...

Future<Either<User, ApiFailure>> fetchUser() async {
  return parseApiResponse(
    requestAction: () => dio.get('/user'),
    mapper: User.fromJson,
  );
}

...instead of this boring code?

Future<Either<User, ApiFailure>> fetchUser() async {
  final dio = Dio(BaseOptions(baseUrl: 'https://example.com'));
  try {
    final request = await dio.get('/user');
    final data = request.data?['data'];
    if (data == null) {
      final error = request.data?['error'];
      if (error != null) {
        return ApiFailure.serverFailure(error['message']);
      } else {
        return ApiFailure.unknown();
      }
    } else {
      return User.fromJson(data);
    }
  } catch (error, st) {
    ApiFailure? apiFailure;
    if (error is DioError) {
      final responseFailure = error.response?.data;
      if (responseFailure is Map<String, dynamic>) {
        apiFailure = ApiFailure.serverFailure(responseFailure['message']);
      } else {
        apiFailure = ApiFailure.httpError(error.response?.statusCode);
      }
    }
    return apiFailure ?? ApiFailure.unknown();
  }
}

Then continue reading!

Usage

To do so, you need to do a little preparation.
For example, let's assume your server returns such response:

{
  "data": {
    // Data you requested
  },
  "error": {
    // Server error which you should parse and show to user
    "message": "Something went wrong"
  }
}

And your error model looks this way:

class ApiFailure {
  factory ApiFailure.unknown() = _UnknownApiFailure;
  factory ApiFailure.serverFailure(String errorMessage) = _ServerFailure;
  factory ApiFailure.httpError(int? statusCode) = _HttpError;
}

Then you need to implement dataExtractor, failureParser and errorCatcher this way:

final _exampleResponseParser = ResponseParser<Response, ApiFailure>(
  dataExtractor: (response) => response.data['data']!,
  failureParser: (response) {
    final error = json['error'];
    if (error is Map<String, dynamic>) {
      return ApiFailure.serverFailure(error['message']);
    } else {
      return null;
    }
  },
  errorCatcher: (error, stackTrace) {
    ApiFailure? apiFailure;
    if (error is DioError) {
      apiFailure = ApiFailure.httpError(error.response?.statusCode);
    }
    return apiFailure ?? ApiFailure.unknown();
  },
);

And create top level parseApiResponse, parseListApiResponse and parseEmptyApiResponse functions.

final parseApiResponse = _exampleResponseParser.parseApiResponse;
final parseListApiResponse = _exampleResponseParser.parseListApiResponse;
final parseEmptyApiResponse = _exampleResponseParser.parseEmptyApiResponse;

That's all!
For more info, you can take a look at the example.

Sponsors

Qyre Logo

About

Response Parser makes it easier to parse data and error response from server.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages