json_error_clarity 0.3.0
json_error_clarity: ^0.3.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, zero dependencies. No Flutter, no
build_runner. Works on server, CLI, Flutter, and web. - β Zero overhead on success β the diagnosis is only built when a parse actually fails.
- β Short by default, verbose on demand β see Error verbosity.
- π« 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.3.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:
//
// β JSON field 'id': expected int, got String ("42")
// π‘ int.parse('42')
Short and to the point. Need the full tutorial-style breakdown? See Error verbosity.
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
Error verbosity #
By default, errors are compact β a couple of lines with the field, the expected vs actual type, the value, and one fix hint. If you want the full tutorial-style breakdown (diagnosis block, type comparison, multiple fix options, copy-paste solutions), switch to verbose once at startup:
JsonErrorClarity.verbosity = ClarityVerbosity.verbose;
Set it back to ClarityVerbosity.compact at any time. The setting is global.
Migrating from 0.1.x / 0.2.x #
From 0.1.x β the @SafeJsonParsing() code generator is gone. Replace
generated fromJsonSafe() calls with explicit accessors in your own fromJson:
// 0.1.x β generated
final user = UserSafeJsonParsing.fromJsonSafe(json);
// now β 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, the
part '...safe_json_parsing.g.dart'; directives, and the @SafeJsonParsing /
@SafeJsonField / @SafeJsonConfig annotations β those annotations were
removed in 0.3.0 and no longer exist.
From 0.2.x β errors are now compact by default instead of the long
tutorial format. Set JsonErrorClarity.verbosity = ClarityVerbosity.verbose to
restore the old output (see Error verbosity). The init
CLI was also removed.
License #
MIT β see LICENSE.
Built to complement json_annotation
and json_serializable.