Skip to content

feat: implement first version of sealed class serialization #1483

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
38 changes: 38 additions & 0 deletions example/lib/sealed_class_example.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import 'package:json_annotation/json_annotation.dart';

part 'sealed_class_example.g.dart';

@JsonSerializable(
unionDiscriminator: 'runtimeType',
unionRename: UnionRename.snake,
)
sealed class MySealedClass {
MySealedClass(this.value);

factory MySealedClass.fromJson(Map<String, dynamic> json) =>
_$MySealedClassFromJson(json);

String value;

Map<String, dynamic> toJson() => _$MySealedClassToJson(this);
}

@JsonSerializable()
class FirstSubtype extends MySealedClass {
final String someAttribute;

FirstSubtype(
this.someAttribute,
super.value,
);
}

@JsonSerializable()
class SecondSubtype extends MySealedClass {
final String someOtherAttribute;

SecondSubtype(
this.someOtherAttribute,
super.value,
);
}
53 changes: 53 additions & 0 deletions example/lib/sealed_class_example.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions json_annotation/lib/src/allowed_keys_helpers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,23 @@ class UnrecognizedKeysException extends BadKeyException {
: super._(map);
}

/// Exception thrown if there is an unrecognized union type in a JSON map
/// that was provided during deserialization.
class UnrecognizedUnionTypeException extends BadKeyException {
/// The discriminator that was not recognized.
final String unrecognizedType;

/// The type of the union that was being deserialized.
final Type unionType;

@override
String get message => 'Unrecognized type: $unrecognizedType '
'for union: $unionType.';

UnrecognizedUnionTypeException(this.unrecognizedType, this.unionType, Map map)
: super._(map);
}

/// Exception thrown if there are missing required keys in a JSON map that was
/// provided during deserialization.
class MissingRequiredKeysException extends BadKeyException {
Expand Down
40 changes: 40 additions & 0 deletions json_annotation/lib/src/json_serializable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,26 @@ enum FieldRename {
screamingSnake,
}

/// Values for the automatic class renaming behavior for [JsonSerializable]
/// with sealed classes.
enum UnionRename {
/// Use the union class name without changes.
none,

/// Encodes union class named `KebabCase` with a JSON key `kebab-case`.
kebab,

/// Encodes union class named `SnakeCase` with a JSON key `snake_case`.
snake,

/// Encodes union class named `PascalCase` with a JSON key `PascalCase`.
pascal,

/// Encodes union class named `ScreamingSnakeCase` with a JSON key
/// `SCREAMING_SNAKE_CASE`
screamingSnake,
}

/// An annotation used to specify a class to generate code for.
@JsonSerializable(
checked: true,
Expand Down Expand Up @@ -162,6 +182,20 @@ class JsonSerializable {
/// fields annotated with [JsonKey].
final FieldRename? fieldRename;

/// Defines the automatic naming strategy when converting class names
/// to union type names.
///
/// With a value [UnionRename.none] (the default), the name of the class is
/// used without modification.
///
/// See [UnionRename] for details on the other options.
final UnionRename? unionRename;

/// The discriminator key used to identify the union type.
///
/// Defaults to `type`.
final String? unionDiscriminator;

/// When `true` on classes with type parameters (generic types), extra
/// "helper" parameters will be generated for `fromJson` and/or `toJson` to
/// support serializing values of those types.
Expand Down Expand Up @@ -271,6 +305,8 @@ class JsonSerializable {
this.disallowUnrecognizedKeys,
this.explicitToJson,
this.fieldRename,
this.unionRename,
this.unionDiscriminator,
this.ignoreUnannotated,
this.includeIfNull,
this.converters,
Expand All @@ -293,6 +329,8 @@ class JsonSerializable {
disallowUnrecognizedKeys: false,
explicitToJson: false,
fieldRename: FieldRename.none,
unionRename: UnionRename.none,
unionDiscriminator: 'type',
ignoreUnannotated: false,
includeIfNull: true,
genericArgumentFactories: false,
Expand All @@ -314,6 +352,8 @@ class JsonSerializable {
disallowUnrecognizedKeys ?? defaults.disallowUnrecognizedKeys,
explicitToJson: explicitToJson ?? defaults.explicitToJson,
fieldRename: fieldRename ?? defaults.fieldRename,
unionRename: unionRename ?? defaults.unionRename,
unionDiscriminator: unionDiscriminator ?? defaults.unionDiscriminator,
ignoreUnannotated: ignoreUnannotated ?? defaults.ignoreUnannotated,
includeIfNull: includeIfNull ?? defaults.includeIfNull,
genericArgumentFactories:
Expand Down
18 changes: 18 additions & 0 deletions json_annotation/lib/src/json_serializable.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading