json_error_clarity 0.2.0
json_error_clarity: ^0.2.0 copied to clipboard
Transform cryptic JSON parsing errors into crystal-clear, actionable error messages. Perfect companion to json_annotation.
JSON Error Clarity π #
Stop wrestling with cryptic JSON parsing errors. json_error_clarity is a
small, pure-Dart package that turns unhelpful cast failures into messages that
tell you exactly which field failed, what type it expected, what it actually
got, and how to fix it.
type 'String' is not a subtype of type 'int' in type cast
β¦becomes a message that names the field, shows the value, and hands you copy-paste fixes.
What it is (and isn't) #
It's a set of extension methods on Map<String, dynamic> β getSafeInt,
getSafeString, getSafeList, requireKeys, and friends β that you call from
your own fromJson. Nothing else runs; there is no build step.
- β Pure Dart. No Flutter dependency. Works on server, CLI, Flutter, and web.
- β
Four dependencies:
json_annotation,meta,args,path. - β Zero overhead on success β the detailed diagnosis is only built when a parse actually fails.
- π« No code generation. The old
@SafeJsonParsing()generator was removed in 0.2.0 (see Migrating from 0.1.x).
Install #
dependencies:
json_error_clarity: ^0.2.0
dart pub add json_error_clarity
Quick start #
Call the safe accessors inside your own fromJson:
import 'package:json_error_clarity/json_error_clarity.dart';
class User {
final int id;
final String name;
final String? email;
final List<String> tags;
User({required this.id, required this.name, this.email, required this.tags});
factory User.fromJson(Map<String, dynamic> json) => User(
id: json.getSafeInt('id'),
name: json.getSafeString('name'),
email: json.getNullableSafeString('email'), // null-safe: missing/null is fine
tags: json.getSafeList('tags', (v) => v as String),
);
}
When the data is well-formed, these return the value and get out of your way. When it isn't, you get a precise error instead of a stack trace.
Before vs after #
final json = {'id': '42', 'name': 'Ada'}; // id arrived as a String
// Plain Dart:
json['id'] as int;
// β type 'String' is not a subtype of type 'int' in type cast
// With json_error_clarity:
json.getSafeInt('id');
// β throws FormatException whose message reads:
//
// π¨ OOPS! There's a problem with your JSON data:
//
// π EXACT PROBLEM DIAGNOSIS:
// π Field name: 'id'
// β
Property EXISTS in JSON: YES
// β Data type MATCHES model: NO
//
// π TYPE COMPARISON:
// π― Your model expects: a whole number (like 42)
// π JSON response contains: text (like 'hello')
// π The actual value: 42
//
// π§ How to fix this (3 easy options): β¦copy-paste solutionsβ¦
The message distinguishes the three ways parsing actually fails:
| Situation | What the message says |
|---|---|
| Key present, wrong type | field name, expected vs actual type, value, fixes |
| Key missing | that the property is not in the JSON, plus "did you mean" suggestions |
Key present but null |
that the value is null β not a type mismatch |
| Bad element in a list | the failing index and that element's value |
API at a glance #
// Required β throw a clear FormatException on failure:
json.getSafe<T>('key', (v) => ...); // custom parser
json.getSafeInt('key');
json.getSafeDouble('key');
json.getSafeString('key');
json.getSafeBool('key'); // accepts true/false, 1/0, 'true'/'yes'/β¦
json.getSafeDateTime('key'); // ISO 8601, or unix seconds/millis
json.getSafeList<T>('key', (v) => ...);
json.getSafeObject<T>('key', T.fromJson);
json.getSafeObjectList<T>('key', T.fromJson);
// Nullable β return null when the key is missing or the value is null:
json.getNullableSafeInt('key'); // β¦and String/Double/Bool/DateTime/List/Object
// Up-front validation:
json.requireKeys(['id', 'name', 'email']);
Handling the error #
Every failure throws a FormatException whose message is the detailed
diagnosis. Catch it once, at your data-source or repository layer:
try {
final user = User.fromJson(payload);
} on FormatException catch (error) {
logger.error(error.message); // the full, human-readable diagnosis
throw DataParseFailure(error.message);
}
There's a runnable demo:
dart run example/main.dart
Migrating from 0.1.x #
0.2.0 removes the @SafeJsonParsing() code generator and the Flutter SDK
dependency. If you used the generator, replace generated fromJsonSafe() calls
with explicit accessors in your own fromJson:
// 0.1.x β generated
final user = UserSafeJsonParsing.fromJsonSafe(json);
// 0.2.0 β explicit, no build step
final user = User(
id: json.getSafeInt('id'),
name: json.getSafeString('name'),
email: json.getNullableSafeString('email'),
);
Then remove the json_error_clarity builder from your build.yaml and the
part '...safe_json_parsing.g.dart'; directives.
The SafeJsonParsing, SafeJsonField, and SafeJsonConfig annotations are
deprecated and will be removed in 0.3.0. Nothing reads them; they remain
only so existing annotated source keeps compiling.
License #
MIT β see LICENSE.
Built to complement json_annotation
and json_serializable.