You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dart中如何序列化抽象类AnimationDecorationInstance的列表为JSON?

Dart抽象类列表的JSON序列化解决方案

问题场景

需要将抽象类型AnimationDecorationInstance的列表序列化为JSON,用于定义屏幕动画集合。列表中包含TextEffect、FilterEffect等不同子类实例,通过AnimationDecorationType枚举区分类型,但使用json_annotation生成代码时出现错误,提示无法为抽象类生成fromJson代码。

现有代码

import 'package:json_annotation/json_annotation.dart';

part 'animation_decoration.g.dart';

@JsonEnum()
enum AnimationDecorationType { text, filter }

@JsonSerializable(explicitToJson: true)
abstract class AnimationDecorationInstance {
  get getArtifactDecorationType;
}

@JsonSerializable(explicitToJson: true)
class AnimationDecoration {
  List<AnimationDecorationInstance> animationDecorations = [];

  AnimationDecoration();

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

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

@JsonSerializable(explicitToJson: true)
class TextEffect with AnimationDecorationInstance {
  final AnimationDecorationType animation_decoration_type =
      AnimationDecorationType.text;

  @override
  get getArtifactDecorationType => animation_decoration_type;

  double fromMillis = 0, toMillis = 0;

  String text = "";

  TextEffect();

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

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

@JsonSerializable(explicitToJson: true)
class FilterEffect with AnimationDecorationInstance {
  final AnimationDecorationType animation_decoration_type =
      AnimationDecorationType.filter;

  @override
  get getArtifactDecorationType => animation_decoration_type;

  int colorFilterAdaper = 0;


  FilterEffect();

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

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

}

错误信息

2022-07-24 12:54:23 Could not generate `fromJson` code for `animationDecorations` because of type `AnimationDecorationInstance`.
2022-07-24 12:54:23 package:sdg4/dto/animation_decoration.dart:14:37
2022-07-24 12:54:23    ╷
2022-07-24 12:54:23 14 │   List<AnimationDecorationInstance> animationDecorations = [];
2022-07-24 12:54:23    │                                     ^^^^^^^^^^^^^^^^^^^^
2022-07-24 12:54:23    ╵

解决方案:自定义JsonConverter处理多态序列化

json_annotation无法自动处理抽象类的多态序列化,需要自定义JsonConverter来根据类型字段区分并转换子类实例。

步骤1:修正抽象类继承关系

抽象类应使用继承而非混入(with),调整子类的继承方式:

abstract class AnimationDecorationInstance {
  AnimationDecorationType get getArtifactDecorationType;
  Map<String, dynamic> toJson();
}

class TextEffect extends AnimationDecorationInstance { ... }
class FilterEffect extends AnimationDecorationInstance { ... }

步骤2:创建自定义转换类

实现JsonConverter,负责序列化/反序列化时的类型判断与转换:

class AnimationDecorationConverter
    implements JsonConverter<AnimationDecorationInstance, Map<String, dynamic>> {
  const AnimationDecorationConverter();

  @override
  AnimationDecorationInstance fromJson(Map<String, dynamic> json) {
    final type = AnimationDecorationType.values.byName(json['animation_decoration_type']);
    switch (type) {
      case AnimationDecorationType.text:
        return TextEffect.fromJson(json);
      case AnimationDecorationType.filter:
        return FilterEffect.fromJson(json);
      default:
        throw Exception('Unknown animation decoration type: $type');
    }
  }

  @override
  Map<String, dynamic> toJson(AnimationDecorationInstance object) {
    return object.toJson();
  }
}

步骤3:为列表字段绑定转换器

在AnimationDecoration类的animationDecorations字段上添加转换器注解:

@JsonSerializable(explicitToJson: true)
class AnimationDecoration {
  @JsonKey(converter: AnimationDecorationConverter())
  List<AnimationDecorationInstance> animationDecorations = [];

  AnimationDecoration();

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

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

完整修改后代码

import 'package:json_annotation/json_annotation.dart';

part 'animation_decoration.g.dart';

@JsonEnum()
enum AnimationDecorationType { text, filter }

abstract class AnimationDecorationInstance {
  AnimationDecorationType get getArtifactDecorationType;
  Map<String, dynamic> toJson();
}

class AnimationDecorationConverter
    implements JsonConverter<AnimationDecorationInstance, Map<String, dynamic>> {
  const AnimationDecorationConverter();

  @override
  AnimationDecorationInstance fromJson(Map<String, dynamic> json) {
    final type = AnimationDecorationType.values.byName(json['animation_decoration_type']);
    switch (type) {
      case AnimationDecorationType.text:
        return TextEffect.fromJson(json);
      case AnimationDecorationType.filter:
        return FilterEffect.fromJson(json);
      default:
        throw Exception('Unknown animation decoration type: $type');
    }
  }

  @override
  Map<String, dynamic> toJson(AnimationDecorationInstance object) {
    return object.toJson();
  }
}

@JsonSerializable(explicitToJson: true)
class AnimationDecoration {
  @JsonKey(converter: AnimationDecorationConverter())
  List<AnimationDecorationInstance> animationDecorations = [];

  AnimationDecoration();

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

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

@JsonSerializable(explicitToJson: true)
class TextEffect extends AnimationDecorationInstance {
  final AnimationDecorationType animation_decoration_type =
      AnimationDecorationType.text;

  @override
  AnimationDecorationType get getArtifactDecorationType => animation_decoration_type;

  double fromMillis = 0, toMillis = 0;
  String text = "";

  TextEffect();

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

  @override
  Map<String, dynamic> toJson() => _$TextEffectToJson(this);
}

@JsonSerializable(explicitToJson: true)
class FilterEffect extends AnimationDecorationInstance {
  final AnimationDecorationType animation_decoration_type =
      AnimationDecorationType.filter;

  @override
  AnimationDecorationType get getArtifactDecorationType => animation_decoration_type;

  int colorFilterAdaper = 0;

  FilterEffect();

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

  @override
  Map<String, dynamic> toJson() => _$FilterEffectToJson(this);
}

重新生成序列化代码

执行命令重新生成代码:

flutter pub run build_runner build

内容的提问来源于stack exchange,提问作者Defarine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 20:16:09