Skip to content

Final field in grand parent are not serialized #1493

Open
@logicinplay

Description

@logicinplay

When a class extend an abstract class that also extends another abstract class, the final field are not serialized. Example:

A extends FooBar<String>
FooBar<T> extends Bar<T>
Bar<T> extends Foo
Foo { final MyEnum myEnum } // myEnum is not serialized

// or
B extends Bar<String>
Bar<T> extends Foo
Foo { final MyEnum myEnum } // myEnum is not serialized

Full example

abstract class Foo {
  final MyEnum myEnum;

  String? name;

  Foo({required this.myEnum});
}

abstract class Bar<T> extends Foo {
  T? value;

  Bar({required super.myEnum});
}

abstract class FooBar<T> extends Bar<T> {
  final MyOtherEnum myOtherEnum;

  final String? otherName;

  FooBar({required this.myOtherEnum, this.otherName})
      : super(myEnum: MyEnum.fooBar);
}

@JsonSerializable()
class A extends FooBar<String> {
  A({required super.myOtherEnum, super.otherName});

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

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

@JsonSerializable()
class B extends Bar<String> {
  B() : super(myEnum: MyEnum.b);

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

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

enum MyEnum { fooBar, b }

enum MyOtherEnum {
  one,
  two,
  three,
}

Generated toJson for A

Map<String, dynamic> _$AToJson(A instance) {
  final val = <String, dynamic>{};

  void writeNotNull(String key, dynamic value) {
    if (value != null) {
      val[key] = value;
    }
  }

  // all fields are here except `myEnum`
  writeNotNull('name', instance.name);
  writeNotNull('value', instance.value);
  val['myOtherEnum'] = _$MyOtherEnumEnumMap[instance.myOtherEnum]!;
  writeNotNull('otherName', instance.otherName);
  return val;
}

Generated toJson for B

Map<String, dynamic> _$BToJson(B instance) {
  final val = <String, dynamic>{};

  void writeNotNull(String key, dynamic value) {
    if (value != null) {
      val[key] = value;
    }
  }

  // all fields are here except `myEnum`
  writeNotNull('name', instance.name);
  writeNotNull('value', instance.value);
  return val;
}

Tried changing myEnum to private field with public getter with @JsonKey() but did not worked.
Removing final for myEnum works.

However, I myEnum should be a final field.

Is there any that I am missing? Any help would be greatly appreciated!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions