json_error_clarity 0.3.0 copy "json_error_clarity: ^0.3.0" to clipboard
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 πŸ” #

pub package License: MIT

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.

1
likes
160
points
116
downloads

Documentation

API reference

Publisher

verified publisherkhokan.me

Weekly Downloads

Transform cryptic JSON parsing errors into crystal-clear, actionable error messages. Perfect companion to json_annotation.

Homepage
Repository (GitHub)
View/report issues

License

MIT (license)

More

Packages that depend on json_error_clarity