JSON Extension Type (JET)
A Dart CLI tool that automatically generates extension types for JSON to Dart typedef records and classes conversion.
Features
- โ Typedef records: Support for Dart typedef records
- ๐งช Classes: Support for Dart classes with constructors (โ ๏ธ Experimental)
- โ Primitive types: String, int, double, bool
- โ Nullable types: Support for nullable fields (?)
- โ Lists: List
- โ Enums: Automatic string to enum conversion
- โ Custom types: Nested record types and classes
- โ Custom annotations: Customize JSON keys and default values
Installation
Global activation
dart pub global activate json_extension_type
Usage
Basic Command
jet generate [path]
Examples
# Generate extensions for lib/ directory
jet generate
# Generate for a specific directory
jet generate lib/models
# Show help
jet help
# Show version
jet --version
How It Works
1. Define Your Model
Create a *_model.dart file with typedef records or classes:
// lib/models/user_model.dart
enum UserStatus {
active,
inactive,
banned,
}
// Option 1: Using typedef records
typedef User = ({
String id,
String name,
String email,
int age,
UserStatus status,
Address? address,
List<String> tags,
});
// Option 2: Using classes (โ ๏ธ Experimental - May change in future releases)
class Person {
final String id;
final String name;
final int age;
final UserStatus status;
Person({
required this.id,
required this.name,
required this.age,
required this.status,
});
}
typedef Address = ({
String street,
String city,
String country,
});
2. Generate Extensions
Run the generator:
jet generate lib/models
3. Generated Code
The tool automatically adds extension types to your model file with clear comments:
// ==========================================
// Generated by JSON Extension Type (JET)
// Do not modify manually
// Run "jet generate" to update
// ==========================================
extension type UserJson(dynamic data) {
User toModel() {
return (
id: data['id'] as String? ?? '',
name: data['name'] as String? ?? '',
email: data['email'] as String? ?? '',
age: data['age'] as int? ?? 0,
status: UserStatus.values.byName(data['status'] as String? ?? 'active'),
address: data['address'] != null ? AddressJson(data['address'] as Map<String, Object?>?).toModel() : null,
tags: (data['tags'] as List?)?.cast<String>() ?? [],
);
}
List<User> toList() {
final data = this.data as List;
return data.map((e) => UserJson(e).toModel()).toList();
}
}
extension type AddressJson(dynamic data) {
Address toModel() {
return (
street: data['street'] as String? ?? '',
city: data['city'] as String? ?? '',
country: data['country'] as String? ?? '',
);
}
List<Address> toList() {
final data = this.data as List;
return data.map((e) => AddressJson(e).toModel()).toList();
}
}
4. Use in Your Code
import 'package:yourapp/models/user_model.dart';
void main() {
final jsonData = {
'id': 'user-123',
'name': 'John Doe',
'email': 'john@example.com',
'age': 30,
'status': 'active',
'address': {
'street': '123 Main St',
'city': 'New York',
'country': 'USA',
},
'tags': ['developer', 'flutter'],
};
// Convert JSON to model
final user = UserJson(jsonData).toModel();
print(user.name); // John Doe
print(user.status); // UserStatus.active
// Convert JSON array
final jsonList = [jsonData, /* ... */];
final users = UserJson(jsonList).toList();
}
Custom Annotations
#key: Custom JSON Key
Map a different JSON key to a field:
typedef User = ({
//#key:user_id
String id,
String name,
});
Generated code:
id: data['user_id'] as String? ?? '',
#default: Custom Default Value
Set a custom default value:
typedef Config = ({
//#default:10
int timeout,
//#default:true
bool enabled,
});
Generated code:
timeout: data['timeout'] as int? ?? 10,
enabled: data['enabled'] as bool? ?? true,
Combined Annotations
typedef Product = ({
//#key:product_id #default:unknown
String id,
//#key:product_price #default:0.0
double price,
});
Type Support
Primitive Types
Stringโ default:''intโ default:0doubleโ default:0.0boolโ default:false
Nullable Types
typedef User = ({
String? nickname, // Can be null
int? age, // Can be null
});
Lists
typedef User = ({
List<String> tags, // List of primitives
List<Product> products, // List of custom types
});
Enums
enum Status { active, inactive, pending }
typedef User = ({
Status status, // Non-nullable enum
Status? role, // Nullable enum
});
Custom Types
typedef Order = ({
User customer, // Non-nullable custom type
Address? billing, // Nullable custom type
});
Project Structure
your_project/
โโโ lib/
โ โโโ models/
โ โโโ user_model.dart # Your models + generated extensions
โ โโโ product_model.dart # Your models + generated extensions
CLI Options
Commands
generate [path]- Generate extensions for modelshelp- Show help message
Flags
-h, --help- Show help-v, --version- Show version
Development
Run from source
cd json_extension_type
dart run bin/jet.dart generate path/to/models
Run tests
dart test
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT License - see LICENSE file for details
Examples
The /example directory contains complete, runnable examples:
basic_example.dart- Simple typedef records and basic conversionsnested_types_example.dart- Complex nested structures (products, categories, reviews)custom_annotations_example.dart- Using#keyand#defaultannotationsapi_simulation_example.dart- Real-world API integration patterns
Run any example:
dart run example/basic_example.dart
See example/README.md for detailed documentation.
Links
- ๐ฆ Package: https://pub.dev/packages/json_extension_type
- ๐ป Repository: https://github.com/babakoto/json_extension_type
- ๐ Issues: https://github.com/babakoto/json_extension_type/issues
Libraries
- code_generator
- generator
- json_extension_type
- JSON Extension Type Generator
- models
- parser