codec 1.0.0
codec: ^1.0.0 copied to clipboard
Type-safe, composable JSON codecs for Dart: structured CodecException with $.path on failure. Nested objects, discriminated unions, recursion, multi-version compatibility.
// Minimal runnable example: hand-written type-safe JSON encode/decode with
// Codec.object, throwing FormatException with `$.path` on failure.
//
// Run: dart run example/codec_example.dart
import 'package:codec/codec.dart';
final class UserModel {
const UserModel({required this.name, this.avatar, required this.age});
final String name;
final String? avatar;
final int age;
static final Codec<UserModel> codec = Codec.object<UserModel>((o) {
final name = o.required('name', Codec.string, encode: (u) => u.name);
final avatar =
o.optional('avatar', Codec.string, encode: (u) => u.avatar).omitNull;
final age =
o.optional('age', Codec.integer, encode: (u) => u.age).defaultTo(0);
return o.create((v) => UserModel(
name: v.get(name),
avatar: v.get(avatar),
age: v.get(age),
));
}).withFormatExceptions();
factory UserModel.fromJson(Object? json) =>
codec.decode(json, typeHint: 'UserModel');
Object? toJson() => codec.encode(this);
}
void main() {
// Successful decode.
final user = UserModel.fromJson({'name': 'Ada', 'age': 36});
print('decoded: name=${user.name}, age=${user.age}');
// Round-trip encode; omitNulls omits avatar.
print('encoded: ${user.toJson()}');
// Failure carries the exact path.
try {
UserModel.fromJson({'name': 'Bob', 'age': 'not-a-number'});
} on FormatException catch (e) {
print('error: ${e.message}');
}
}