zorphy_annotation은 zorphy 생태계 내에서 코드 생성을 위한 Dart 패키지입니다. 개발자가 깔끔하고 유지보수 가능한 클래스를 정의할 수 있도록 하며, copyWith, JSON 직렬화, toString, 동등성 검사 및 상속을 내장된 지원 기능으로 제공합니다. 간단한 어노테이션을 적용함으로써 개발자는 봐야 할 코드(보일러플레이트)를 자동으로 생성할 수 있어 오류를 줄이고 개발 속도를 향상시킬 수 있습니다. 이 패키지는 Flutter 및 기타 Dart 플랫폼과 원활하게 통합되어 다양한 환경에서 데이터 모델을 관리하는 데 이상적입니다.
사용 사례
불변 데이터 클래스 생성
JSON 직렬화 자동화
재사용 가능한 모델 클래스 만들기
상태 관리 간소화
copyWith를 사용하여 깊은 복사 활성화
크로스 플랫폼 앱 개발 지원
주요 기능
자동 copyWith 메서드 생성
내장된 JSON 직렬화 지원
동등성 및 toString 메서드 생성
상속 인식 코드 생성
주석을 사용한 최소한의 뼈대 코드
크로스 플랫폼 호환성
적합한 대상
데이터 모델을 사용하는 Flutter 개발자
코드 정결성을 우선시하는 팀
JSON 처리가 필요한 프로젝트
불변 객체가 필요한 앱
코드 생성 도구를 사용하는 개발자
다중 플랫폼을 대상으로 하는 프로젝트
고려 사항
코드 생성 빌드 단계가 필요합니다
zorphy의 코드 생성기 의존
빌드 시간을 늘릴 수 있습니다
올바른 주석 설정이 필요합니다
추가 구성 없이 제한된 사용자 지정 가능
zorphy_core와 함께 사용하는 것이 가장 좋습니다
원본 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