Dart抽象类子类JSON解析异常:子类属性无法获取值
子类属性丢失原因及解决方案
问题原因
你在Car.fromJson工厂方法中,创建子类Cabrio实例后,错误地重新给承载实例的变量赋值了一个新对象(比如错误调用父类构造创建新实例、覆盖了之前的Cabrio对象),导致原本带有正确子类属性的实例被丢弃,最终返回的是仅包含父类属性的对象,自然roofMaterial、someOtherProp会是null。
调试时看到Cabrio.fromJson能正确赋值,是因为该方法确实生成了正确的实例,但后续在Car.fromJson中这个实例被替换成了新的、没有子类属性的对象。
正确实现方式
方式1:父类封装公共属性初始化方法
把id、name这类公共属性的解析逻辑封装在父类的方法里,子类实例创建后直接调用该方法,避免重复代码:
abstract class Car { String? id; String? name; Car(); // 封装公共属性的解析逻辑 void _initCommonProps(Map<String, dynamic> json) { id = json['id']; name = json['name']; } factory Car.fromJson(Map<String, dynamic> json) { late Car car; switch(json['type']) { case 'cabrio': car = Cabrio.fromJson(json); break; // 其他子类的分支 default: throw UnsupportedError('未知的车辆类型'); } // 在子类实例上初始化公共属性 car._initCommonProps(json); return car; } } class Cabrio extends Car { String? roofMaterial; String? someOtherProp; Cabrio(); factory Cabrio.fromJson(Map<String, dynamic> json) { final cabrio = Cabrio(); // 先赋值子类独有的属性 cabrio.roofMaterial = json['roofMaterial']; cabrio.someOtherProp = json['someOtherProp']; return cabrio; } }
方式2:子类构造函数复用父类公共构造
父类定义专门处理公共属性的命名构造,子类构造函数调用该构造,同时完成自身属性的解析:
abstract class Car { String? id; String? name; // 父类命名构造:处理公共属性 Car.fromCommonJson(Map<String, dynamic> json) : id = json['id'], name = json['name']; factory Car.fromJson(Map<String, dynamic> json) { switch(json['type']) { case 'cabrio': return Cabrio.fromJson(json); // 其他子类分支 default: throw UnsupportedError('未知的车辆类型'); } } } class Cabrio extends Car { String? roofMaterial; String? someOtherProp; // 子类构造函数调用父类公共构造,同时解析自身属性 Cabrio.fromJson(Map<String, dynamic> json) : roofMaterial = json['roofMaterial'], someOtherProp = json['someOtherProp'], super.fromCommonJson(json); }
你可能踩的错误示例
这种写法会直接覆盖子类实例,导致属性丢失:
abstract class Car { String? id; String? name; Car(this.id, this.name); factory Car.fromJson(Map<String, dynamic> json) { Car car; if (json['type'] == 'cabrio') { car = Cabrio.fromJson(json); // 这里的cabrio实例是正确的 } // 错误:重新赋值car,丢弃了之前的Cabrio实例 car = Car(json['id'], json['name']); // Car是抽象类,实际编译不通过,仅作错误示例 return car; } }
内容的提问来源于stack exchange,提问作者MwBakker
相关产品推荐
相关产品推荐

