input.json
order.dart
extension type const Order(Map<String, dynamic> json) { factory Order.fromJson(Map<String, dynamic> json) => Order(json); String get orderId => json["order_id"] as String; Customer get customer => Customer.fromJson(json["customer"] as Map<String, dynamic>); double get total => (json["total"] as num).toDouble(); DateTime get createdAt => DateTime.parse(json["created_at"] as String); List<Item> get items => (json["items"] as List<dynamic>).map((e) => Item.fromJson(e as Map<String, dynamic>)).toList(); Map<String, dynamic> toJson() => json; } extension type const Customer(Map<String, dynamic> json) { factory Customer.fromJson(Map<String, dynamic> json) => Customer(json); String get firstName => json["first_name"] as String; String get email => json["email"] as String; bool get isVerified => json["is_verified"] as bool; Map<String, dynamic> toJson() => json; } extension type const Item(Map<String, dynamic> json) { factory Item.fromJson(Map<String, dynamic> json) => Item(json); String get sku => json["sku"] as String; int get quantity => json["quantity"] as int; double get price => (json["price"] as num).toDouble(); String? get note => json["note"] == null ? null : json["note"] as String; Map<String, dynamic> toJson() => json; }
Convert JSON to Dart extension types
This mode creates extension types with the JSON map as their representation and typed getters for inferred fields. Nested objects are exposed through nested extension types; toJson returns the underlying map.
Use Dart 3.3 or newer. Copy the output into a Dart file and pass a decoded Map<String, dynamic> to the generated fromJson factory. These are views of the input map, so mutations to that map remain observable through the getters.