Zorphy는 copyWith, JSON 직렬화, toString, 동등성 검사 및 상속을 내장된 지원과 함께 깔끔하고 유지보수 가능한 클래스를 쉽게 만들 수 있도록 도와주는 Dart/Flutter 코드 생성 패키지입니다. 주석 기반으로 필수 메서드를 자동으로 생성함으로써 반복적인 코드를 줄이고 코드 가독성과 개발 생산성을 향상시킵니다. 최소한의 수동 구현으로 구조화된 데이터 모델이 필요한 프로젝트에 이상적입니다.
사용 사례
불변 데이터 클래스 생성
JSON 직렬화 자동화
재사용 가능한 모델 클래스 만들기
상태 관리 간소화
copyWith를 사용한 객체 복사의 용이성 활성화
생성된 클래스에서 상속 지원
주요 기능
자동 copyWith 메서드 생성
내장된 JSON 직렬화
생성된 toString 및 동등성 메서드
생성된 클래스에서의 상속 지원
주석을 사용한 최소한의 뼈대 코드
크로스 플랫폼 호환성
적합한 대상
상태 관리를 사용하는 플러터 개발자
코드 일관성을 우선시하는 팀
중요한 데이터 모델링을 포함하는 프로젝트
JSON 파싱이 필요한 앱
보일러플레이트를 줄이려는 개발자
코드 생성 워크플로우를 사용하는 사용자
고려 사항
코드 생성 개념에 대한 이해가 필요합니다
컴파일을 위해 build_runner가 필요합니다
빌드 시간을 약간 증가시킬 수 있습니다
Zorphy 지시어로 주석이 달린 클래스에 한정
정확한 주석 사용에 의존
동적 또는 런타임 전용 구조에 적합하지 않습니다
원본 README
연결된 소스 저장소의 README 원문 스냅샷입니다. 최신 내용은 저장소에서 확인하세요.
Zorphy
Zorphy is a powerful code generation package for Dart/Flutter that provides clean, immutable class definitions with advanced features including copyWith methods, JSON serialization, equality, toString, inheritance support, and sophisticated patch mechanisms.
Sponsor
Thanks to ZikZak AI for sponsoring this project!
ZikZak AI is an AI-Powered Price Comparison app that you scan barcodes, and discover amazing savings instantly. Your personal shopping assistant that never sleeps.
📖 Documentation
Visit the official documentation at arrrrny.github.io/zorphy for detailed guides, examples, and API references.
🏷️ Field-Selector CopyWith - copyWithField(Field<E, T> field, T value) replaces a single field via the typed Field selector; passing null to a nullable field preserves the current value
🎯 Function-based CopyWith - Optional function-based copyWith for computed updates
🔧 Patch System - Advanced patching mechanism for partial updates with nested support
📦 JSON Serialization - Full toJson/fromJson support with polymorphic type handling
⚖️ Equality - Auto-generated == operator and hashCode
📝 toString - Meaningful string representations for debugging
🔐 Sealed Classes - Support for sealed classes with exhaustiveness checking
🌳 Self-Referencing Types - Handle tree structures and hierarchical data
🏭 Factory Methods - Support for custom factory constructors
🧬 Inheritance & Polymorphism - Multiple inheritance, generics, and interfaces
🔢 Enum Support - Full enum integration with JSON serialization
📊 CompareTo - Generate comparison methods showing differences between instances
🔄 ChangeTo - Convert between related types in inheritance hierarchies
🤖 AI-Friendly CLI - Command-line tool optimized for AI agents and developers
🔌 MCP Server - Model Context Protocol server for agentic integration
⚖️ Zorphy vs Freezed
Both generate immutable data classes. Zorphy goes further — it is a full
entity toolkit with a nested patch system, filter/query descriptors,
compareTo diffs, and an AI-agent CLI/MCP server.
Capability
zorphy 2.0
freezed 3.2.5
Immutable data classes + copyWith
✅
✅
Function-based copyWith (copyWithFn)
✅ opt-in (ZorphyPreset.full)
❌
JSON + polymorphic discriminators + toJsonLean
✅
✅ (no toJsonLean)
Sealed unions
✅ sealed $$Base + Dart 3 pattern matching
✅ via when/map helpers
Nested patch system (partial updates of deep graphs)
Where freezed differs (honest notes): freezed's mixin pattern
(with _$Foo) keeps the annotated class itself concrete; zorphy uses
abstract class $Foo + generated Foo. freezed's when/map helpers
are answered in zorphy by Dart 3's native exhaustive switch on the
sealed base. Freezed's ecosystem is older and larger.
It converts simple classes, sealed unions, @Default, @JsonKey, and
fromJson/toJson automatically, and reports anything that needs human
attention with file:line — nothing is silently dropped. See the
migration guide.
@Zorphy()
abstractclass $TodoList{
Stringget title;
List<Todo> get todos;
}
// Update specific item in listfinal patch = TodoListPatch.create()
..updateTodosAt(0, (todoPatch) => todoPatch
..withCompleted(true)
..withTitle('Updated Title'));
Functional Patches
// Using functions for computed updatesfinal patch = CounterPatch.create()
..withValue((current) => current + 1);
final updated = counter.patchWithCounter(patchInput: patch);
@Zorphy()
abstractclass $$Base<T> {
T get value;
}
@Zorphy()
abstractclass $Derived<Textendsnum> implements $$Base<T> {
@override
T get value;
T get doubled => value * 2;
}
6. Explicit Subtypes & ChangeTo
Use explicitSubTypes to enable cross-type operations:
@Zorphy()
abstractclass $User{
Stringget name;
String? get email;
String? get phone;
}
final user = User(name: 'Alice');
// email and phone are nullfinal withEmail = user.copyWith(email: 'alice@example.com');
14. Complex Nested Structures
@Zorphy()
abstractclass $Company{
Stringget name;
List<Department> get departments;
}
@Zorphy()
abstractclass $Department{
Stringget name;
List<Employee> get employees;
}
@Zorphy()
abstractclass $Employee{
Stringget name;
String? get title;
}
// Deep nesting with proper JSON supportfinal company = Company(
name: 'Tech Corp',
departments: [
Department(
name: 'Engineering',
employees: [
Employee(name: 'Alice', title: 'Engineer'),
],
),
],
);
15. Generic Fields and Methods
typedefJsonConverter<T> = T Function(dynamic);
@Zorphy()
abstractclass $ApiResponse<T> {
boolget success;
T? get data;
String? get error;
}
@Zorphy()
abstractclass $UserListResponseimplements $ApiResponse<List<User>> {
@overrideboolget success;
@overrideList<User>? get data;
@overrideString? get error;
}
# Build once
dart run build_runner build
# Build and watch for changes
dart run build_runner watch
# Clean generated files
dart run build_runner clean
# Or use the CLI
zorphy build
zorphy build --watch
zorphy build --clean
📝 Naming Conventions
Class Prefixes
$ClassName - Concrete class definition (use ClassName in code)
$$ClassName - Sealed abstract class (exhaustiveness checking)
$ClassName_ - Class with hidden private constructor
Generated Files
*.zorphy.dart - Generated code from @Zorphy annotation
Generated Enums
ClassName$ - Enum of field names for patch system
Generated Patch Classes
ClassNamePatch - Patch class for partial updates
🔄 Migration from Morphy
Zorphy is designed for easy migration from Morphy:
Replace @Morphy with @Zorphy
Replace morphy_annotation dependency with zorphy_annotation
Replace zikzak_morphy dependency with zorphy
Run dart run build_runner clean
Run dart run build_runner build
Key Differences:
Better patch system with nested support
Enhanced generic handling
Improved error messages
More flexible inheritance patterns
Built-in CLI and MCP server for AI agents
🐛 Troubleshooting
Type Not Found Errors
If you get type not found errors, ensure:
You've added part 'filename.zorphy.dart'; to your file
You've run dart run build_runner build or zorphy build
The import includes package:zorphy_annotation/zorphy_annotation.dart
Generic Type Issues
When using generics, ensure type parameter names match between parent and child:
Note:@Zorphy2 is deprecated in v2. The single-pass v2 generator handles ordering automatically — you no longer need to annotate build-order dependencies manually.
If you are migrating from v1 code that uses @Zorphy2, simply replace all @Zorphy2() annotations with @Zorphy() — the v2 generator will resolve the correct build order.
License
MIT License - see LICENSE file for details
Acknowledgments
Inspired by and designed to improve upon the Morphy code generation package.
Made with 🔥 by the ZikZak AI team for the community and AI agents