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

Dart中如何通过字符串形式的变量引用路径获取对应变量值

Dart 按字符串路径访问对象属性方案

你不需要逐一手写所有类的toJson()方法,以下是按改造成本从低到高排序的可落地方案:


方案1:基于dart:mirrors的原生反射实现(零改造成本,仅支持纯Dart环境)

如果你的项目是Dart命令行工具、服务端应用,没有Flutter跨端编译限制,可以直接用Dart内置的镜像反射能力实现路径访问,完全不需要修改任何现有业务类代码。
工具函数实现:

import 'dart:mirrors';

/// 按路径从根对象上获取属性值,路径段用.分隔
dynamic getValueByPath(dynamic root, String propertyPath) {
  final pathSegments = propertyPath.split('.');
  dynamic currentValue = root;
  for (final segment in pathSegments) {
    if (currentValue == null) return null;
    final instanceMirror = reflect(currentValue);
    currentValue = instanceMirror.getField(Symbol(segment)).reflectee;
  }
  return currentValue;
}

使用示例:

class A {
  B b = B();
}

class B {
  String c = "apple";
}

void main() {
  A a = A();
  // 注意路径不需要带根实例名a,因为我们直接传入a作为根对象
  final ref = "b.c";
  print(getValueByPath(a, ref)); // 输出apple
}

注意:Flutter 移动端/桌面端/Web端编译时禁用了dart:mirrors,这类跨端场景不能使用本方案


方案2:代码生成自动序列化+路径遍历(兼容所有Flutter/Dart场景,改造成本极低)

手写toJson()成本高的问题完全可以通过代码生成解决,不需要你手动写任何嵌套序列化逻辑:

  1. 引入依赖:生产环境依赖json_annotation,开发环境依赖build_runner和json_serializable
  2. 给所有需要支持动态路径访问的类加固定注解和模板方法,不需要写具体序列化逻辑:
    import 'package:json_annotation/json_annotation.dart';
    // 指向生成的代码文件,文件名和你当前的dart文件名一致即可
    part 'demo.g.dart';
    
    @JsonSerializable(explicitToJson: true)
    class A {
      B b = B();
      // 以下两行是固定模板,所有类写法完全一致
      factory A.fromJson(Map<String, dynamic> json) => _$AFromJson(json);
      Map<String, dynamic> toJson() => _$AToJson(this);
    }
    
    @JsonSerializable(explicitToJson: true)
    class B {
      String c = "apple";
      factory B.fromJson(Map<String, dynamic> json) => _$BFromJson(json);
      Map<String, dynamic> toJson() => _$BToJson(this);
    }
    
  3. 执行命令dart run build_runner build,所有类的嵌套toJson()/fromJson()逻辑会自动生成,后续类字段修改后只需要重跑该命令即可更新逻辑
  4. 实现通用路径访问工具:
    dynamic getValueByPath(dynamic rootObj, String propertyPath) {
      // 自动调用生成的toJson转成嵌套Map,无需手写转换逻辑
      final Map<String, dynamic> rootMap = rootObj.toJson();
      final pathSegments = propertyPath.split('.');
      dynamic current = rootMap;
      for (final seg in pathSegments) {
        // 支持数组索引访问,比如路径b.itemList.0.name
        final index = int.tryParse(seg);
        if (index != null && current is List) {
          current = current[index];
          continue;
        }
        if (current is! Map || !current.containsKey(seg)) return null;
        current = current[seg];
      }
      return current;
    }
    

本方案优势:

  • 全平台兼容,没有Flutter反射限制
  • 性能好,所有逻辑在编译期生成,没有运行时反射开销
  • 改造成本极低,只需要给类加注解和两行固定模板,不需要手写任何嵌套转换逻辑,是Flutter生态的主流实现方式

方案3:代码生成式反射(适合复杂动态场景)

如果你需要的不只是属性读取,还要支持动态修改属性、调用方法等更灵活的反射能力,可以使用reflectable包。它的原理是在编译期只生成你标记过的类的反射元数据,不会带来全量反射的包体积问题,全平台兼容。
使用时只需要给需要支持反射的类加自定义注解,跑build命令生成反射代码后,就可以写出和dart:mirrors体验几乎一致的路径访问逻辑,不需要实现toJson方法,灵活度比序列化方案更高,适合动态规则、动态表单这类复杂场景。


选型建议

  • 纯Dart服务端/脚本场景优先选方案1,零改造成本
  • Flutter应用仅需要按路径读属性优先选方案2,生态最成熟、坑最少
  • 需要复杂动态反射能力选方案3

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 16:09:21