response_parser 1.1.2 copy "response_parser: ^1.1.2" to clipboard
response_parser: ^1.1.2 copied to clipboard

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

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

License: MIT Pub

Getting started #

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

Future<Either<ApiFailure, User>> fetchUser() async {
  return parseApiResponse(
    requestAction: () => dio.get('/user'),
    mapper: User.fromJson,
  );
}
...instead of this boring code?
Future<Either<ApiFailure, User>> 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 left(ApiFailure.serverFailure(error['message']));
      } else {
        return left(ApiFailure.unknown());
      }
    } else {
      return right(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 left(apiFailure ?? ApiFailure.unknown());
  }
}

Then continue reading!

Don't know what is `Either`?

It's a type from fpdart package. It's used to return either error (left) or data (right).

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;

How it works #

This diagram shows how parseApiResponse works under the hood:

parseApiResponse diagram

Actually, everything in the parseApiResponse method is wrapped with the try-catch block. So this method is safe and can't throw any exceptions.

Another way to use #

Instead of creating top-level functions, you can create a class which extends ResponseParserBase and overrides it's methods:

class DefaultResponseParser extends ResponseParser<Response, ApiFailure>{
  Object extractData(Response response) => response.data['data']!;

  Failure? parseFailure(Response response) {
    final error = json['error'];
    if (error is Map<String, dynamic>) {
      return ApiFailure.serverFailure(error['message']);
    } else {
      return null;
    }
  };

  Failure catchError(Object error, StackTrace stackTrace) {
    ApiFailure? apiFailure;
    if (error is DioError) {
      apiFailure = ApiFailure.httpError(error.response?.statusCode);
    }

    return apiFailure ?? ApiFailure.unknown();
  };
}

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

7
likes
160
pub points
5%
popularity

Publisher

unverified uploader

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

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

fpdart

More

Packages that depend on response_parser