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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 16:25:35