Flutter中Json序列化toJson方法缺失父抽象类type字段问题
子类toJson缺失父类type字段的原因及修复方案
问题核心
json_serializable默认不会自动将父类字段纳入子类的序列化输出,除非父类配置了完整的序列化逻辑,且子类显式合并父类的序列化结果。你的代码存在两个关键问题:
- 父类
FormFieldModel仅添加了@JsonSerializable(createFactory: false)注解,但未定义抽象toJson方法,导致生成器无法为父类生成序列化逻辑,子类自然无法继承父类字段的序列化规则。 - 枚举
FormFieldType未配置序列化注解,当前的反序列化逻辑依赖字符串拼接,不够简洁安全;同时序列化时会输出FormFieldType.text这类带前缀的字符串,不符合常规JSON格式。
修复步骤
- 给父类添加抽象
toJson方法,让生成器生成父类字段的序列化逻辑 - 子类重写
toJson时,合并父类与自身的序列化结果 - 给枚举添加
@JsonEnum注解,优化序列化/反序列化行为 - 修正
WizNumberField中写错的工厂方法名(原代码写成了GWizNumberField.fromJson)
修改后的完整代码
import 'package:json_annotation/json_annotation.dart'; part 'temp.g.dart'; // 配置枚举序列化时输出纯名称字符串(如'text'而非'FormFieldType.text') @JsonEnum(valueField: 'name') enum FormFieldType { text, number, } @JsonSerializable(createFactory: false) abstract class FormFieldModel { final String label; final FormFieldType type; final bool isRequired; FormFieldModel({required this.label, required this.type, this.isRequired = true}); // 新增抽象方法,触发生成器生成父类的toJson逻辑 Map<String, dynamic> toJson(); static FormFieldModel fromJson(Map<String, dynamic> json) { // 用byName替代原字符串拼接逻辑,更简洁安全 final type = FormFieldType.values.byName(json['type']); switch (type) { case FormFieldType.text: return WizTextField.fromJson(json); case FormFieldType.number: return WizNumberField.fromJson(json); } } } @JsonSerializable() class WizTextField extends FormFieldModel { final int? minLength; final int? maxLength; WizTextField({ required String label, this.minLength, this.maxLength, bool isRequired = true, }) : super(label: label, type: FormFieldType.text, isRequired: isRequired); factory WizTextField.fromJson(Map<String, dynamic> json) => _$WizTextFieldFromJson(json); @override Map<String, dynamic> toJson() { // 合并父类与子类的序列化结果 final parentJson = super.toJson(); final childJson = _$WizTextFieldToJson(this); parentJson.addAll(childJson); return parentJson; } } @JsonSerializable() class WizNumberField extends FormFieldModel { final int? min; final int? max; WizNumberField({ required String label, this.min, this.max, bool isRequired = true, }) : super(label: label, type: FormFieldType.number, isRequired: isRequired); // 修正原代码中写错的工厂方法名 factory WizNumberField.fromJson(Map<String, dynamic> json) => _$WizNumberFieldFromJson(json); @override Map<String, dynamic> toJson() { final parentJson = super.toJson(); final childJson = _$WizNumberFieldToJson(this); parentJson.addAll(childJson); return parentJson; } }
修复后生成的代码效果
运行dart run build_runner build后,生成器会为父类生成包含type、label、isRequired的序列化逻辑,子类仅生成自身字段的序列化代码,最终合并后的toJson输出会包含所有预期字段:
// 父类生成的序列化逻辑 Map<String, dynamic> _$FormFieldModelToJson(FormFieldModel instance) => <String, dynamic>{ 'label': instance.label, 'type': _$FormFieldTypeEnumMap[instance.type]!, 'isRequired': instance.isRequired, }; const _$FormFieldTypeEnumMap = { FormFieldType.text: 'text', FormFieldType.number: 'number', }; // 子类生成的序列化逻辑仅包含自身字段 Map<String, dynamic> _$WizNumberFieldToJson(WizNumberField instance) => <String, dynamic>{ 'min': instance.min, 'max': instance.max, };
内容的提问来源于stack exchange,提问作者Ouroboros
相关产品推荐
相关产品推荐

