By annotating the class, the code required for the "Value Class" is automatically generated.
Inspired by json_serializable and freezed.
Flutter project:
flutter pub add value_annotation
flutter pub add --dev build_runner
flutter pub add --dev value_class
flutter pub get
Dart project:
dart pub add value_annotation
dart pub add --dev build_runner
dart pub add --dev value_class
dart pub get
import 'package:value_annotation/value_annotation.dart';
part 'example.value.dart';
@valueClass
class Example with _$Example {
const factory Example(String value) = _Example;
const factory Example.fromJson(String value) = _Example;
}
Flutter project:
flutter pub run build_runner build
Dart project:
dart run build_runner build
Similar to freezed, you can use @Assert
to add assert(...)
statement to the generated class.
Note
Unlike freezed, the first argument of@Assert
is aFunction
instead of aString
to reduce typos. Therefore, the constructor cannot be given the const modifier.
import 'package:value_annotation/value_annotation.dart';
part 'email.value.dart';
@valueClass
class Email with _$Email {
@Assert(_checkNotEmpty, 'Email cannot be empty')
@Assert(_checkFormat, 'Email format is invalid')
factory Email(String value) = _Email;
}
bool _checkNotEmpty(String value) => value.isNotEmpty;
bool _checkFormat(String value) => value.contains(RegExp(r'^.+@\S+\.\S+$'));
This package supports the combination of json_serializable and freezed.
See the example directory.
import 'package:value_annotation/value_annotation.dart';
part 'email.value.dart';
@valueClass
class Email with _$Email {
@Assert(_checkNotEmpty, 'Email cannot be empty')
@Assert(_checkFormat, 'Email format is invalid')
factory Email(String value) = _Email;
factory Email.fromJson(String value) = _Email;
}
bool _checkNotEmpty(String value) => value.isNotEmpty;
bool _checkFormat(String value) => value.contains(RegExp(r'^.+@\S+\.\S+$'));
import 'package:example/model/email.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'person.freezed.dart';
part 'person.g.dart';
@freezed
class Person with _$Person {
const factory Person({
required Email email,
}) = _Person;
factory Person.fromJson(Map<String, Object?> json) => _$PersonFromJson(json);
}
import 'dart:convert';
import 'package:example/model/email.dart';
import 'package:example/model/person.dart';
import 'package:simple_logger/simple_logger.dart';
void main() {
final personBefore = Person(email: Email('example@gmail.com'));
final encoded = jsonEncode(personBefore);
final decoded = jsonDecode(encoded) as Map<String, dynamic>;
final personAfter = Person.fromJson(decoded);
SimpleLogger()
..info('Encoded: $encoded')
..info('Decoded: $personAfter')
..info('Equals: ${personBefore == personAfter}');
}
Executing main()
will output following log.
👻 INFO 2022-08-05 01:20:40.412135 [caller info not available] Encoded: {"email":"example@gmail.com"}
👻 INFO 2022-08-05 01:20:40.414220 [caller info not available] Decoded: Person(email: Email(value: example@gmail.com))
👻 INFO 2022-08-05 01:20:40.414812 [caller info not available] Equals: true
Process finished with exit code 0
The following Types in the dart:core library are supported:
More types will be supported in the future.
You should follow our Code of Conduct.
See Contributor Guide for contributing conventions.
blendthink |