FlutterArtist DIO ErrorInfoExtractor
ErrorInfoExtractor is a base class used to extract error information from a JSON formatted error returned from the server.
ErrorInfoExtractor
abstract class ErrorInfoExtractor {
const ErrorInfoExtractor();
String? extractErrorMessage({required Map<String, dynamic> errorJson});
List<String>? extractErrorDetails({required Map<String, dynamic> errorJson});
}The following example is one of the most common error templates:
{
"code": "INVALID_INPUT",
"message": "The provided data is invalid.",
"details": [
"Email address is not in a valid format.",
"Password must be at least 8 characters long."
]
}The purpose of ErrorInfoExtractor is to extract error information and assign it to the errorMessage and errorDetails properties of an ApiError object.
- errorMessage: The provided data is invalid.
- errorDetails: ["Email address is not in a valid format.", "Password must be at least 8 characters long."]
ApiError
class ApiError extends AppError {
ApiErrorType? errorType;
int? statusCode;
String? statusMessage;
String? originErrorText;
dynamic Function(Map<String, dynamic> value)? usedConverter;
ApiError({
this.statusCode,
this.statusMessage,
this.errorType,
this.originErrorText,
required super.errorMessage, // <-----------
super.errorDetails, // <-----------
this.usedConverter,
});
}No ADS
ErrorInfoExtractor is used as a parameter in the constructor of FlutterArtistDio (a Dio wrapper), making it easy to exchange data between the application and the server.
- FlutterArtist Rest Debug Viewer
1. FlexibleErrorInfoExtractor
In the real world, each API may return a different error structure, but through ErrorInfoExtractor, we unify everything into a single ApiError format. "Guessing" every type of Backend error is like playing the lottery; a good ErrorInfoExtractor not only handles what we see but must also be prepared for what we haven't seen yet. FlutterArtistprovides a built-in FlexibleErrorInfoExtractor capable of extracting errors from most common error formats today.
FlexibleErrorInfoExtractor
class FlexibleErrorInfoExtractor extends ErrorInfoExtractor {
final List<String> messageKeys;
final List<String> detailKeys;
/// Custom function to convert a detail object to a string.
/// If not provided, the system will use the default Stringify mechanism.
final String Function(dynamic detail)? detailStringifier;
const FlexibleErrorInfoExtractor({
this.messageKeys = const [
"message",
"errorMessage",
"error",
"msg",
"title",
],
this.detailKeys = const ["details", "errorDetails", "errors", "detail"],
this.detailStringifier,
});
...
} Below are the common JSON error formats and the extraction results when using FlexibleErrorInfoExtractor:
Template: Simple Flat
{
"message": "Invalid username or password",
"code": 401
}- errorMessage: Invalid username or password
- errorDetails: null
Template: Validation Details
{
"message": "The provided data is invalid.",
"details": [
{ "field": "email", "message": "Invalid format" },
{ "field": "password", "message": "Too short" }
]
}- errorMessage: The provided data is invalid.
- errorDetails: ["email: Invalid format", "password: Too short"]
No ADS
Template: The Global Error
{
"errors": {
"global": ["System maintenance", "Try again later"],
"auth": ["Token expired"]
}
}- errorMessage: null
- errorDetails: "global: System maintenance, Try again later", "auth: Token expired"]
Template: Nested Object
{
"error": {
"innerError": {
"code": "5001",
"message": "Database connection failed"
}
}
}- errorMessage: null
- errorDetails: ["{innerError: {code: 5001, message: Database connection failed}}"]
Template: Validation Summary (.NET/Laravel style)
{
"errors": {
"username": ["Name already exists", "Too short"],
"password": ["Missing numeric character"]
}
}- errorMessage: null
- errorDetails: ["username: Name already exists, Too short" , "password: Missing numeric character"]
2. Use a custom FlexibleErrorInfoExtractor.
If your Backend doesn't use keywords like message or details but uses reason and error_list instead, you can easily redefine them.
final customExtractor = FlexibleErrorInfoExtractor(
// Search for these keys for errorMessage
messageKeys: ["reason", "status_text", "msg"],
// Search for these keys for errorDetails
detailKeys: ["error_list", "validation_errors"],
);
final dio = FlutterArtistDio(
dio: myDio,
errorInfoExtractor: customExtractor,
);What sets FlexibleErrorInfoExtractor apart is its "adaptability." Instead of passively waiting for a fixed structure, it actively searches through messageKeys and detailKeys to find the most useful information. This is crucial when working with various Backend services within the same project.
If you want to completely change how an error Object is displayed on the screen, use detailStringifier. This is the most "powerful" feature for experts.
final advancedExtractor = FlexibleErrorInfoExtractor(
detailStringifier: (detail) {
if (detail is Map<String, dynamic>) {
final code = detail['code'];
final desc = detail['desc'];
return "[$code] - $desc";
}
return detail.toString();
},
);No ADS