【问题标题】:How to define a model with a property that can be both null or another model in Dart如何在 Dart 中定义一个属性既可以是 null 也可以是另一个模型的模型
【发布时间】:2020-09-15 11:59:33
【问题描述】:

我正在构建一个 Flutter 应用,但在定义模型时遇到了一些麻烦。我有具有一些属性的模型。其中一个属性可以为 null 或其他模型。

import 'package:proef/models/worked_time.dart';

class Shift {
  String uuid;
  DateTime start_at;
  DateTime end_at;
  String title;
  String comment;
  WorkedTime worked_time;

  Shift(
      {this.uuid,
      this.start_at,
      this.end_at,
      this.title,
      this.comment,
      this.worked_time});

  factory Shift.fromData(Map<String, dynamic> parsedJson) {
    print(parsedJson);
    return Shift(
        uuid: parsedJson['uuid'],
        start_at: DateTime.parse(parsedJson['start_at']).toLocal(),
        end_at: DateTime.parse(parsedJson['end_at']).toLocal(),
        title: parsedJson['title'],
        comment: parsedJson['comment'],
        worked_time: parsedJson['worked_time'] == null
            ? null
            : parsedJson['worked_time']);
  }
}

这不起作用。当我使用这个模型时,它会抛出以下错误:

Unhandled Exception: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'WorkedTime'

我不知道如何解决这个问题,因为我对 Dart 和 Flutter 还很陌生。

WorkedTime 模型:

class WorkedTime {
  String uuid;
  String comment;
  int status;
  int took_break;
  DateTime start_at;
  DateTime end_at;

  WorkedTime({
    this.uuid,
    this.comment,
    this.status,
    this.took_break,
    this.start_at,
    this.end_at,
  });

  factory WorkedTime.fromData(Map<String, dynamic> parsedJson) {
    print(parsedJson);
    return WorkedTime(
        uuid: parsedJson['uuid'],
        comment: parsedJson['comment'],
        status: parsedJson['status'],
        took_break: parsedJson['took_break'],
        start_at: DateTime.parse(parsedJson['start_at']),
        end_at: DateTime.parse(parsedJson['end_at']));
  }
}

带有工作时间的 JSON

[
    {
        "uuid": "706f40e7-d57c-470c-9023-b0c58e2c7c3a",
        "start_at": "2020-09-01T08:00:00.000000Z",
        "end_at": "2020-09-01T16:00:00.000000Z",
        "title": "Test",
        "comment": "Test",
        "worked_time": {
            "uuid": "6e73b4aa-d6e1-41f7-86cb-09745d2db033",
            "comment": "Test",
            "status": 0,
            "break": 0,
            "start_at": "2020-09-01T08:00:00.000000Z",
            "end_at": "2020-09-01T16:00:00.000000Z",
            "took_break": 0
        }
    }
]

没有工作时间的 JSON

[
    {
        "uuid": "706f40e7-d57c-470c-9023-b0c58e2c7c3a",
        "start_at": "2020-09-01T08:00:00.000000Z",
        "end_at": "2020-09-01T16:00:00.000000Z",
        "title": "Test",
        "comment": "Test",
        "worked_time": null
    }
]

【问题讨论】:

  • 你能显示你的 json 以便我可以建议你一个工厂代码
  • 将 JSON 添加到描述中。提前致谢!

标签: json flutter dart model


【解决方案1】:

你可以试试这个模型

// To parse this JSON data, do
//
//     final shift = shiftFromJson(jsonString);

import 'dart:convert';

List<Shift> shiftFromJson(String str) => List<Shift>.from(json.decode(str).map((x) => Shift.fromJson(x)));

String shiftToJson(List<Shift> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class Shift {
    Shift({
        this.uuid,
        this.startAt,
        this.endAt,
        this.title,
        this.comment,
        this.workedTime,
    });

    String uuid;
    DateTime startAt;
    DateTime endAt;
    String title;
    String comment;
    WorkedTime workedTime;

    factory Shift.fromJson(Map<String, dynamic> json) => Shift(
        uuid: json["uuid"] == null ? null : json["uuid"],
        startAt: json["start_at"] == null ? null : DateTime.parse(json["start_at"]),
        endAt: json["end_at"] == null ? null : DateTime.parse(json["end_at"]),
        title: json["title"] == null ? null : json["title"],
        comment: json["comment"] == null ? null : json["comment"],
        workedTime: json["worked_time"] == null ? null : WorkedTime.fromJson(json["worked_time"]),
    );

    Map<String, dynamic> toJson() => {
        "uuid": uuid == null ? null : uuid,
        "start_at": startAt == null ? null : startAt.toIso8601String(),
        "end_at": endAt == null ? null : endAt.toIso8601String(),
        "title": title == null ? null : title,
        "comment": comment == null ? null : comment,
        "worked_time": workedTime == null ? null : workedTime.toJson(),
    };
}

class WorkedTime {
    WorkedTime({
        this.uuid,
        this.comment,
        this.status,
        this.workedTimeBreak,
        this.startAt,
        this.endAt,
        this.tookBreak,
    });

    String uuid;
    String comment;
    int status;
    int workedTimeBreak;
    DateTime startAt;
    DateTime endAt;
    int tookBreak;

    factory WorkedTime.fromJson(Map<String, dynamic> json) => WorkedTime(
        uuid: json["uuid"] == null ? null : json["uuid"],
        comment: json["comment"] == null ? null : json["comment"],
        status: json["status"] == null ? null : json["status"],
        workedTimeBreak: json["break"] == null ? null : json["break"],
        startAt: json["start_at"] == null ? null : DateTime.parse(json["start_at"]),
        endAt: json["end_at"] == null ? null : DateTime.parse(json["end_at"]),
        tookBreak: json["took_break"] == null ? null : json["took_break"],
    );

    Map<String, dynamic> toJson() => {
        "uuid": uuid == null ? null : uuid,
        "comment": comment == null ? null : comment,
        "status": status == null ? null : status,
        "break": workedTimeBreak == null ? null : workedTimeBreak,
        "start_at": startAt == null ? null : startAt.toIso8601String(),
        "end_at": endAt == null ? null : endAt.toIso8601String(),
        "took_break": tookBreak == null ? null : tookBreak,
    };
}

【讨论】:

    【解决方案2】:

    编译器不会抱怨将dynamic 变量分配给类型化变量,因为检查是在运行时完成的。因此,你可以这样写:

    void main() {
      dynamic value = "something";
      String string = value; // ok, value holds a String; runtime is fine
      WorkedTime time = value; // evaluated at runtime; exception
    }
    

    Shift 的工厂构造函数中存在此问题:

    worked_time: parsedJson['worked_time'] == null
                ? null                        // true: can assign null to WorkedTime
                : parsedJson['worked_time']); // false: assign dynamic to WorkedTime
    

    您正在尝试将值为 parsedJson['worked_time'] 的 dynamic 类型分配给您的 WorkedTime 类型。这些是不兼容的类型。相反,您必须使用 WorkedTime 的构造函数从 JSON 映射构造实例。这是您的问题的一个缩小示例:

    class WorkedTime {
      String comment;
    
      WorkedTime.fromData(Map<String, dynamic> json) : comment = json['comment'];
    }
    
    class Shift {
      String uuid;
      WorkedTime worked_time;
    
      Shift.fromData(Map<String, dynamic> json)
          : uuid = json['uuid'],
            // next line causes the exception; cannot assign dynamic to WorkedTime
            // fix: use WorkedTime.fromData(json['worked_time'])
            worked_time = json['worked_time'];
    }
    

    为了解决这个问题,请使用WorkedTime.fromData(...) 的构造函数。

    class Shift {
      String uuid;
      WorkedTime worked_time;
    
      Shift.fromData(Map<String, dynamic> json)
          : uuid = json['uuid'],
            worked_time = json['worked_time'] != null
                ? WorkedTime.fromData(json['worked_time']) // parse WorkedTime's json
                : null;
    }
    
    void main() {
      const json = <String, dynamic>{
        'uuid': '706f40e7-d57c-470c-9023-b0c58e2c7c3a',
        'worked_time': <String, dynamic>{'comment': 'on break'}
      };
    
      final shift = Shift.fromData(json);
    
      // check that shift.worked_time is not null, etc.
      print(shift.worked_time.comment);
    }
    

    【讨论】:

      猜你喜欢
      • 2018-11-26
      • 2016-08-25
      • 2014-10-24
      • 2021-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-04
      • 1970-01-01
      相关资源
      最近更新 更多