response_parser

Last updated:

0 purchases

response_parser Image
response_parser Images
Add to Cart

Description:

response parser

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<ApiFailure, User>> fetchUser() async {
return parseApiResponse(
requestAction: () => dio.get('/user'),
mapper: User.fromJson,
);
}
copied to clipboard

...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());
}
}
copied to clipboard

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"
}
}
copied to clipboard
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;
}
copied to clipboard
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();
},
);
copied to clipboard
And create top level parseApiResponse, parseListApiResponse and parseEmptyApiResponse functions.
final parseApiResponse = _exampleResponseParser.parseApiResponse;
final parseListApiResponse = _exampleResponseParser.parseListApiResponse;
final parseEmptyApiResponse = _exampleResponseParser.parseEmptyApiResponse;
copied to clipboard
How it works #
This diagram shows how parseApiResponse works under the hood:

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();
};
}
copied to clipboard

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

License:

For personal and professional use. You cannot resell or redistribute these repositories in their original state.

Files In This Product:

Customer Reviews

There are no reviews.