tamed_json

tamed_json is a lightweight and extensible utility for safe and type-aware JSON parsing in Dart.

This package provides:

  • ๐Ÿ”’ Type-safe access to JSON fields
  • โœ… Default fallback (or:) and null-aware access
  • ๐Ÿšจ Custom exceptions for invalid data structures
  • ๐Ÿ—๏ธ A JsonFactory<T> interface for converting models
  • ๐Ÿงฉ Convenient list parsing via factory support

tamed_json helps turn verbose, error-prone JSON parsing into clean, declarative, and resilient code โ€” especially useful in projects with structured API responses and multiple model classes.


Getting started

Add dependency:

dart pub add tamed_json

Features

โœ… Type-safe access to JSON
๐Ÿ’ก or: fallback values on missing or null keys
โš ๏ธ Custom exceptions for invalid structures
๐Ÿ—๏ธ Generic factory support for fromJson and toJson
๐Ÿงช Built-in test coverage

Usage

1. Read values from JSON
import 'package:tamed_json/tamed_json.dart';

final json = {...};

final int count = json.int('count');
final String title = json.string('title');
final double price = json.double('price');
final bool inStock = json.bool('in_stock');
final JsonMap object = json.object('child');
final List list = json.list('list');
1.1 Read nullable values
final int? count = json.intNull('count');
final String? title = json.stringNull('title');
final double? price = json.doubleNull('price');
final bool? inStock = json.boolNull('in_stock');
final JsonMap? object = json.objectNull('child');
final List? list = json.listNull('list');
1.2 Read values with fallback
final int count = json.int('count', or: 0);
1.3 Read values in chain
final int count = json.object('a').int('b');
final int? count = json.objectNull('a')?.int('b');

2. Create factory
class ProductModelJsonFactory implements JsonFactory<ProductModel> {
  const ProductModelJsonFactory();

  @override
  ProductModel fromJson(JsonMap json)=>
    ProductModel(
      price: json.double('price'),
      title: json.string('title'),
    );

  @override
  JsonMap toJson(ProductModel model)=>
    {
      'price': model.price,
      'title': model.title,
    };
}
2.1 Use factory
const productFactory = ProductModelJsonFactory();

final model = productFactory.fromJson(json);
final model = json.factory(productFactory, key: 'product');

final json = productFactory.toJson(model);
2.2 Use factory with list
final List<ProductModel> products = json.factoryList(
  productFactory,
  key: 'products',
);
2.3 Skip invalid data
final List<ProductModel> products = json.factoryList(
  productFactory,
  key: 'products',
  throws: false,
);

3 Combine it as you need
/// EXAMPLE 1
MyModel fromJson(JsonMap json){
    final product = json.object('product').factory(productFactory);
    final List<Tags> tags = json.factoryList(
      productFactory,
      key: 'tags',
    );
    return MyModel(product: product, tags: tags);
}

/// EXAMPLE 2
String extractTitle(JsonMap e) => e.string('title');

final items = json
    .object('data')
    .list('product')
    .map(extractTitle)
    .toList();

Additional information

Exception message format

Type: JsonParseFieldException
Reason: Expected double, but got '12' (String). data['price'] is '12'
Key: price
Data: {price: '12', title: Phone1}
StackTrace: ...

Libraries

tamed_json