JsonSentinel class

Lightweight runtime JSON key and type validation with a configurable logger.

Validates a Map<String, dynamic> against an expected schema — checking key existence and value types — without code generation. Designed for use in tryFromJson methods to catch malformed API responses early.

All methods are static; this class cannot be instantiated.

The fallback logger (used when neither configure nor silence has been called) writes to dart:developer and is suppressed in release builds — always call configure or silence in production code.

Pass verbose: true to either configure or silence to enable trace-level dart:developer logs: a confirmation on initialisation, a success trace on every passing validate call, and a diagnostic when jsonEncode fails. Verbose output is orthogonal to silence.

Quick start

// 1. Wire in your logger once at startup:
JsonSentinel.configure((message, {error, stackTrace, extras, escalate}) {
  myLogger.warn(message, stackTrace: stackTrace, extras: extras, escalate: escalate ?? false);
});

// 2. Validate in tryFromJson:
final result = JsonSentinel.validate(
  json: responseJson,
  expectedTypes: {
    'productId': [int],
    'sku':       [String],
    'price':     [int, double],
    'description': [String, null], // nullable
  },
  optional: {'description'}, // present-or-absent is fine
  context: 'ProductListing',
);
if (!result.isValid) return null;

Properties

hashCode int
The hash code for this object.
no setterinherited
runtimeType Type
A representation of the runtime type of the object.
no setterinherited

Methods

noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toString() String
A string representation of this object.
inherited

Operators

operator ==(Object other) bool
The equality operator.
inherited

Static Properties

logger JsonLogFn?
The configured JsonLogFn, or null if neither configure nor silence has been called.
no setter

Static Methods

configure(JsonLogFn logFn, {bool verbose = false, Set<String>? redactKeys, String redactionPlaceholder = '[REDACTED]'}) → void
Configures the logger used for all validation failures.
resetLoggerForTesting() → void
Resets the logger, verbose flag, and redaction state to their initial values.
silence({bool verbose = false, Set<String>? redactKeys, String redactionPlaceholder = '[REDACTED]'}) → void
Suppresses all validation log output.
validate({required Map<String, dynamic> json, required Map<String, List<Type?>?> expectedTypes, Set<String> optional = const <String>{}, bool strict = false, bool warnUnexpected = false, bool escalate = false, String context = 'UnknownModel', String? parentContext, Map<String, bool Function(Object?)>? validators}) JsonValidationResult
Validates json against expectedTypes and returns a JsonValidationResult.
validateBatch({required List<Map<String, dynamic>> jsons, required Map<String, List<Type?>?> expectedTypes, String context = 'UnknownModel', Set<String> optional = const <String>{}, bool strict = false, bool warnUnexpected = false, bool escalate = false, bool generatePreviews = true, Map<String, bool Function(Object?)>? validators}) BatchValidationResult
Validates each item in jsons against expectedTypes and returns a BatchValidationResult.
validateList({required List raw, required Map<String, List<Type?>?> expectedTypes, String context = 'UnknownModel', Set<String> optional = const <String>{}, bool strict = false, bool warnUnexpected = false, bool escalate = false, bool generatePreviews = true, Map<String, bool Function(Object?)>? validators}) BatchValidationResult
Validates each element in raw against expectedTypes, treating non-Map items as failures.