tryFromJson static method

ErrorResponseModel? tryFromJson(
  1. Map<String, dynamic> json
)

Attempts to parse an ErrorResponseModel from a decoded error response body.

Validates the structure of json using JsonSentinel.validate before parsing. Returns null if validation fails or any field conversion throws, making this safe to call on untrusted API data.

Implementation

static ErrorResponseModel? tryFromJson(Map<String, dynamic> json) {
  final Map<String, List<Type?>?> expectedTypes = <String, List<Type?>?>{
    "code": <Type?>[String],
    "message": <Type?>[String],
    "traceId": <Type?>[String],
    "details": <Type?>[null, List],
  };

  final bool ok = JsonSentinel.validate(
    json: json,
    expectedTypes: expectedTypes,
    optional: const <String>{'details'},
    context: 'ErrorResponseModel',
    escalate: false,
  ).isValid;

  if (!ok) return null;

  try {
    final String code = json["code"] as String;
    final String message = json["message"] as String;
    final String traceId = json["traceId"] as String;
    final List<dynamic>? rawDetails = json["details"] as List<dynamic>?;

    final List<ErrorDetail> details = (rawDetails ?? <dynamic>[])
        .whereType<Map<String, dynamic>>()
        .map(ErrorDetail.tryFromJson)
        .whereType<ErrorDetail>()
        .toList(growable: false);

    return ErrorResponseModel(code: code, message: message, traceId: traceId, details: details);
  } catch (e, st) {
    JsonSentinel.logger?.call(
      '[ErrorResponseModel] Parsing failed after validation.',
      error: e,
      stackTrace: st,
      extras: const <String, Object?>{'model': 'ErrorResponseModel'},
      escalate: false,
    );
    return null;
  }
}