Reputation: 1709
The documentation of freezed is telling that we should just use the sealed classes made available in dart 3. However: it does not explain how to use it, especially in combination with fromJson. So I'm a little stumped on how to do it with sealed classes instead of union types.
Given the following union;
import 'package:freezed_annotation/freezed_annotation.dart';
part 'example.freezed.dart';
part 'example.g.dart';
@freezed
sealed class Example with _$Example {
const factory Example.text({
required String text,
}) = _ExampleText;
const factory Example.nameLocation({
required String name,
required String location,
}) = _ExampleNameLocation;
factory Example.fromJson(
Map<String, dynamic> json,
) =>
_$ExampleFromJson(json);
}
void main() {
print(Example.fromJson({'runtimeType': 'text', 'text': 'Hello'}));
print(Example.fromJson({
'runtimeType': 'nameLocation',
'name': 'John',
'location': 'Amsterdam'
}));
}
I tried something like this - but that doesn't work. (The non-abstract class '_$ExampleTextImpl' is missing implementations for these members: _$Example.toJson)
import 'package:freezed_annotation/freezed_annotation.dart';
part 'example.freezed.dart';
part 'example.g.dart';
@freezed
sealed class Example with _$Example {
const factory Example() = _Example;
factory Example.fromJson(
Map<String, dynamic> json,
) =>
_$ExampleFromJson(json);
}
@freezed
class ExampleText extends Example with _$ExampleText {
const factory ExampleText({required String text}) = _ExampleText;
}
@freezed
class ExampleNameLocation extends Example with _$ExampleNameLocation {
const factory ExampleNameLocation({
required String name,
required String location,
}) = _ExampleNameLocation;
}
void main() {
print(Example.fromJson({'runtimeType': 'ExampleText', 'text': 'Hello'}));
print(Example.fromJson({
'runtimeType': 'ExampleNameLocation',
'name': 'John',
'location': 'Amsterdam'
}));
}
Upvotes: 0
Views: 1424
Reputation: 41
This article describes how to use sealed classes with freezed:
https://tomasrepcik.dev/blog/2024/2024-03-27-freezed-pattern-matching/
import 'package:freezed_annotation/freezed_annotation.dart';
part 'main_screen_state.freezed.dart';
// sealed in front of the main screen
@freezed
sealed class MainScreenState with _$MainScreenState {
const MainScreenState._();
const factory MainScreenState.init() = Init;
const factory MainScreenState.loading() = Loading;
const factory MainScreenState.content(List<String> data) = Content;
}
Usage:
switch (state) {
case Init():
// your logic for Init()
case Loading():
// your logic for Loading()
case Content():
// your logic for Content()
state.data // accessing the internal data - autocast
}
And as for fromJson it will work with runtimeType
: init
, loading
or content
for this example.
Upvotes: 1
Reputation: 1709
Looks like it's the same as before, except we would make the classes not private and freezed will generate the classes after the =
.
import 'package:freezed_annotation/freezed_annotation.dart';
part 'example.freezed.dart';
part 'example.g.dart';
@freezed
sealed class Example with _$Example {
const factory Example.text({
required String text,
}) = ExampleText;
const factory Example.nameLocation({
required String name,
required String location,
}) = ExampleNameLocation;
factory Example.fromJson(Map<String, dynamic> json) =>
_$ExampleFromJson(json);
}
void main() {
final example =
Example.fromJson({'runtimeType': 'text', 'text': 'Hello World!'});
final type = switch (example) {
ExampleText() => 'ExampleText',
ExampleNameLocation() => 'ExampleNameLocation',
};
print(type); // ExampleText
}
I do think this is a little unclear in the documentation, but I guess it's not that much different as before. Just don't use when.
Upvotes: 1
Reputation: 1
To use sealed classes with Freezed in Dart, you don't need to create separate classes for each variant. Instead, you can define all variants within the same sealed class and handle them using pattern matching. Here's how you can modify your code:
import 'package:freezed_annotation/freezed_annotation.dart';
part 'example.freezed.dart';
part 'example.g.dart';
@freezed
abstract class Example with _$Example {
const factory Example.text({
required String text,
}) = _Text;
const factory Example.nameLocation({
required String name,
required String location,
}) = _NameLocation;
factory Example.fromJson(Map<String, dynamic> json) =>
_$ExampleFromJson(json);
}
void main() {
final example1 = Example.fromJson({'runtimeType': 'text', 'text': 'Hello'});
final example2 = Example.fromJson({
'runtimeType': 'nameLocation',
'name': 'John',
'location': 'Amsterdam'
});
example1.when(
text: (String text) => print('Text: $text'),
nameLocation: (String name, String location) =>
print('Name: $name, Location: $location'),
);
example2.when(
text: (String text) => print('Text: $text'),
nameLocation: (String name, String location) =>
print('Name: $name, Location: $location'),
);
}
Upvotes: -1