Attempting to use a abstract base class as a field inside another class causes a code gen error.
eg. extending the working example from an earlier bug:
import 'package:json_annotation/json_annotation.dart';
part 'temp.g.dart';
abstract class ItemCore {
final int price;
ItemCore(this.price);
}
@JsonSerializable()
class Item extends ItemCore {
int count;
int itemNumber;
bool isRushed;
Item(int price) : super(price);
factory Item.fromJson(Map<String, dynamic> json) => _$ItemFromJson(json);
}
@JsonSerializable()
class ItemContainer {
final ItemCore core;
ItemContainer(this.core);
factory ItemContainer.fromJson(Map<String, dynamic> json) =>
_$ItemContainerFromJson(json);
}
causes an error of:
[INFO] Running build...
[SEVERE] json_serializable:json_serializable on lib/models/temp.dart:
Error running JsonSerializableGenerator
Could not generate `fromJson` code for `core`.
None of the provided `TypeHelper` instances support the defined type.
package:flutterette/models/temp.dart:24:18
â•·
24 │ final ItemCore core;
│ ^^^^
╵
[INFO] Running build completed, took 862ms
Changing the field to the inheriting class works fine: final Item core;
As does making the base class not abstract but in my actual codebase I really would like it to be abstract.
Not sure if I am missing something obvious here? Googling around and searching past issues here I haven't found anything to help.
This is using:
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: ^1.7.4
json_serializable: ^3.2.5
and Flutter:
[✓] Flutter (Channel stable, v1.12.13+hotfix.8, on Linux
So my current workaround is to mark the abstract class as serialisable but not generate a fromJson:
@JsonSerializable(createFactory: false)
abstract class Section implements WidgetType {
...
not ideal as the analyzer complains about the unused generated toJson() but at least it means I can have my abstract baseclass and use instances of it in other model classes.
FYI I have a hand written fromJson that works well per your suggestion Kevin in 597 :
factory Section.fromJson(Map<String, dynamic> json) {
if (json != null && json['items'] != null) {
return FixedSection.fromJson(json);
} else {
return ListSection.fromJson(json);
}
}
i had the same problem but decided to convert abstract class into usual. For method bodies I added 'throw UnImplemneted()';
And fromJson is enhanced with switch case:
factory NaturalResource.fromJson(Map<String, dynamic> json) {
switch (json['type']) {
case "FOREST":
return Forest.fromJson(json);
case "RIVER":
return River.fromJson(json);
default:
return _$NaturalResourceFromJson(json);
}
}
Im having this issue but dont understand how you guys solved this one. I have some properties I in the abstract class I want included in the serialisation and deserialisation output however it seems the generated code does not take this in to account for the toJson and fromJson methods generated for the concrete classes. If I do whats @maks mentions then I dont get the serialisation/deserialisation of the abstract classes properties. Or am I missing something?
@muzzah , I converted my abstract class into normal class. Instead of implementing method bodies I just
throw Unimplemented();
To catch not extended method in the children classes.
This falls under the general issue of handling arbitrary types as field values.
To start, you'd likely need to do
@JsonSerializable()
class ItemContainer<T extends ItemCore> {
final T core;
...
Hi @kevmoo,
Bouncing back on this custom model,
factory Section.fromJson(Map<String, dynamic> json) {
if (json != null && json['items'] != null) {
return FixedSection.fromJson(json);
} else {
return ListSection.fromJson(json);
}
}
I would like to implement the same with a long model,
Would you have a mainstream sample ?
Most helpful comment
So my current workaround is to mark the abstract class as serialisable but not generate a fromJson:
not ideal as the analyzer complains about the unused generated
toJson()but at least it means I can have my abstract baseclass and use instances of it in other model classes.FYI I have a hand written fromJson that works well per your suggestion Kevin in 597 :