skip to Main Content

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'
  }));
}

2

Answers


  1. Chosen as BEST ANSWER

    Looks like it's the same as before, except we wound 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
    }
    

  2. 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'),
      );
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search