Как правильно обрабатывать сериализацию карт в JSON с помощью json_serializer в Dart? - PullRequest
0 голосов
/ 26 апреля 2019

Я пытался вернуть Map, вызывая функции toJson моих классов, но я получаю NoSuchMethodError: Класс '_InternalLinkedHashMap' не имеет метода экземпляра 'toJson'.Поэтому я предполагаю, что это не правильно. examples содержит только отдельные значения, которые можно преобразовать в отдельные значения, но не обрабатывает списки или карты.Итак, как правильно обрабатывать сериализацию карт в JSON с помощью json_serializer в Dart?

Класс, который я пытаюсь сериализовать:

class StudentDailyReport {
  final DocumentReference documentReference;
  Student student;

  // CheckIn
  String attendanceStatus;
  bool checkInChanged;
  DateTime checkedInTime;

  DateTime date;

  // CheckOut
  bool get checkedOut => this.attendanceStatus == AttendanceStatus.checkedOut;
  bool checkOutChanged;
  DateTime checkedOutTime;

  // Mood
  Mood mood;
  bool moodHasChanged;
  TextEditingController moodController;

  // Supplies
  Supplies supplies;

  // Notes
  Note note;
  TextEditingController noteController;
  bool noteChanged;

  // Meals
  Map<Meal, MealRecord> mealRecords;
  bool mealsChanged;

  // Health
  Map<int, HealthEntry> healthEntries;
  bool healthChanged;

  //PottyLog
  PottyLog pottyLog;

  bool get pottyLogChanged => pottyLog.hasChanged;

  ActivityLog activityLog;

  bool get activityLogChanged => activityLog.hasChanged;

  set activityLogChanged(bool value) =>
      activityLog = activityLog.copyWith(hasChanged: value);

  List<CaptionedPhoto> photos;

  factory StudentDailyReport.initialFromStudent(Student student) {
    return StudentDailyReport(
        student: student,
        moodController: TextEditingController(),
        healthEntries: {0: HealthEntry.empty()},
        supplies: Supplies(),
        pottyLog: PottyLog.empty(),
        activityLog: ActivityLog());
  }

  StudentDailyReport.fromDocument(DocumentSnapshot document)
      : documentReference = document.reference {
    Map json = document.data;
    // Ensure that the student has been converted and inserted as a student object
    // into the json before calling.
    this.student = json['student'];
    this.mood = json['mood'] != null ? Mood.fromJson(json['mood']) : Mood();
    this.attendanceStatus = json['attendanceStatus'] ?? AttendanceStatus.none;
    this.checkedInTime = json['checkedInTime'] != null
        ? (json['checkedInTime'] as Timestamp).toDate()
        : null;
    this.checkedOutTime = json['checkedOutTime'] != null
        ? (json['checkedOutTime'] as Timestamp).toDate()
        : null;
    this.supplies = json['supplies'] != null
        ? Supplies.fromJson(json['supplies'])
        : Supplies();
    this.note = json['note'] != null ? Note.fromJson(json['note']) : Note();
    noteController = TextEditingController(text: note.comment);
    this.mealRecords = MealRecord.mapFromJsonList(json['mealRecords']);
    this.healthEntries = json['healthEntries'] != null
        ? (json['healthEntries'] as List)
            .map((json) => HealthEntry.fromJson(json))
            .toList()
            .asMap()
        : {0: HealthEntry.empty()};
    this.pottyLog = json["pottyLog"] != null
        ? PottyLog.fromJson(json["pottyLog"])
        : PottyLog();
    this.activityLog = json["activityLog"] != null
        ? ActivityLog.fromJson(json["activityLog"])
        : ActivityLog();
    this.photos = json['photos'] != null
        ? (json['photos'] as List)
            .map((photoJson) => CaptionedPhoto.fromJson(photoJson))
            .toList()
        : List<CaptionedPhoto>();
    this.checkInChanged = false;
    this.checkOutChanged = false;
    this.healthChanged = false;
    this.mealsChanged = false;
    this.noteChanged = false;
    this.moodHasChanged = false;
    this.moodController = TextEditingController();
  }

  bool validateMeals() {
    return mealRecords.values.any((mealRecord) => !mealRecord.isValid);
  }

  /// Used to indicate when changes need to be saved.
  bool get hasUnsavedChanges {
    bool result;
    if (moodHasChanged == null ||
        checkInChanged == null ||
        supplies.suppliesHasChanged == null ||
        checkOutChanged == null ||
        noteChanged == null ||
        checkOutChanged == null ||
        mealsChanged == null ||
        healthChanged == null ||
        pottyLogChanged == null ||
        activityLogChanged == null) {
      debugPrint("One of these is null!");
    }
    try {
      result = moodHasChanged ||
          checkInChanged ||
          supplies.suppliesHasChanged ||
          checkOutChanged ||
          noteChanged ||
          checkOutChanged ||
          mealsChanged ||
          healthChanged ||
          pottyLogChanged ||
          activityLogChanged;
    } on Exception {
      return false;
    }

    return result;
  }

  StudentDailyReport({
    this.documentReference,
    this.student,
    this.date,
    // Mood
    this.mood = const Mood(),
    this.moodHasChanged = false,
    this.moodController,

    // Check In
    this.attendanceStatus = AttendanceStatus.none,
    this.checkInChanged = false,
    this.checkedInTime,

    //Check Out
    this.checkOutChanged = false,
    this.checkedOutTime,

    // Supplies
    this.supplies,
    this.mealRecords = const {},
    this.mealsChanged = false,

    // Notes
    this.noteController,
    this.note = const Note.empty(),
    this.noteChanged = false,

    // Health
    this.healthEntries,
    this.healthChanged = false,

    //PottyLog
    this.pottyLog,

    //ActivityLog
    this.activityLog,
    this.photos,
  }) {
    // assertions
    if (attendanceStatus == AttendanceStatus.present) {
      assert(checkedInTime != null);
    }
    if (attendanceStatus == AttendanceStatus.checkedOut) {
      assert(checkedOutTime != null);
    }
    this.date ??= DateTime.now();
    this.noteController = TextEditingController();
    this.moodController = TextEditingController();
  }

  StudentDailyReport copyWith({
    DocumentReference documentReference,
    Mood mood,
    bool moodChanged,
    bool checkInChanged,
    DateTime checkedInTime,
    bool checkedOut,
    DateTime checkedOutTime,
    bool checkOutChanged,
    TextEditingController moodController,
    String attendanceStatus,
    Note note,
    Supplies supplies,
    TextEditingController notesController,
    bool notesChanged,
    TextEditingController suppliesController,
    bool suppliesChanged,
    bool hasUnsavedChanges,
    Map<Meal, MealRecord> mealRecords,
    bool mealsChanged,
    Map<int, HealthEntry> todaysHealthEntries,
    bool healthChanged,
    PottyLog pottyLog,
    bool pottyLogChanged,
    ActivityLog activityLog,
    bool activityLogChanged,
    List<CaptionedPhoto> photos,
    DateTime date,
  }) {
    return StudentDailyReport(
        documentReference: documentReference ?? this.documentReference,
        student: this.student,
        mood: mood ?? this.mood,
        moodHasChanged: moodChanged ?? this.moodHasChanged,
        checkInChanged: checkInChanged ?? this.checkInChanged,
        attendanceStatus: attendanceStatus ?? this.attendanceStatus,
        checkedInTime: (attendanceStatus == AttendanceStatus.present &&
                checkedInTime == null)
            ? DateTime.now()
            : checkedInTime ?? this.checkedInTime,
        moodController: this.moodController,
        note: note ?? this.note,
        noteController: this.noteController,
        noteChanged: noteChanged ?? this.noteChanged,
        supplies: supplies ?? this.supplies,
        checkOutChanged: checkOutChanged ?? this.checkOutChanged,
        checkedOutTime: attendanceStatus == AttendanceStatus.present &&
                checkedOutTime == null
            ? DateTime.now()
            : this.checkedOutTime,
        mealRecords: mealRecords ?? this.mealRecords,
        mealsChanged: mealsChanged ?? this.mealsChanged,
        healthEntries: todaysHealthEntries ?? this.healthEntries,
        healthChanged: healthChanged ?? this.healthChanged,
        pottyLog: () {
          PottyLog newPottyLog = pottyLog ??= this.pottyLog;
          if (pottyLogChanged == false) {
            return newPottyLog.copyWith(hasChanged: false);
          }
          return newPottyLog;
        }(),
        activityLog: activityLog ?? this.activityLog,
        photos: photos ?? this.photos,
        date: date ?? this.date);
  }

  String get fullName => student.fullName;

  Map<String, dynamic> toJson() {
    Map<String, dynamic> data = {};

    if (this.mood != null && this.mood.mood != "" && this.moodHasChanged) {
      data["mood"] = this.mood.toJson();
    }

    // attendance
    if (this.checkInChanged || this.checkOutChanged) {
      data["attendanceStatus"] = this.attendanceStatus;
    }
    if (this.checkInChanged) {
      assert(checkedInTime != null);
      data['checkedInTime'] = Timestamp.fromDate(this.checkedInTime);
    }
    if (this.checkOutChanged) {
      assert(checkedOutTime != null);
      data['checkedOutTime'] = Timestamp.fromDate(this.checkedOutTime);
    }
    if (this.supplies.suppliesHasChanged) {
      data["supplies"] = this.supplies.toJson();
    }
    if (this.mealsChanged) {
      data['mealRecords'] = this
          .mealRecords
          .values
          .map((mealRecord) => mealRecord.toJson())
          .toList();
    }
    if (this.noteChanged) {
      data['note'] = this.note.toJson();
    }
    data['student'] = this.student.documentReference;
    if (healthChanged) {
      data['healthEntries'] = healthEntries.values
          .map((healthEntry) => healthEntry.toJson())
          .toList();
    }
    if (this.pottyLogChanged) {
      data['pottyLog'] = this.pottyLog.toJson();
    }
    if (this.activityLogChanged) {
      data['activityLog'] = this.activityLog.toJson();
    }
    return data;
  }

  StudentDailyReport updateWith(DocumentSnapshot documentChange) {
    Map json = documentChange.data;

    return StudentDailyReport(
        documentReference: documentChange.reference,
        student: student,
        mood: json['mood'] != null ? Mood.fromJson(json['mood']) : mood,
        attendanceStatus: json['attendanceStatus'] ?? attendanceStatus,
        checkedInTime:
            (json['checkedInTime'] as Timestamp)?.toDate() ?? checkedInTime,
        checkedOutTime:
            (json['checkedOutTime'] as Timestamp)?.toDate() ?? checkedOutTime,
        supplies: json['supplies'] != null
            ? Supplies.fromJson(json['supplies'])
            : supplies,
        note: json['note'] != null ? Note.fromJson(json['note']) : note,
        mealRecords: MealRecord.mapFromJsonList(json['mealRecords']),
        healthEntries: json['healthEntries'] != null
            ? (json['healthEntries'] as List)
                .map((json) => HealthEntry.fromJson(json))
                .toList()
                .asMap()
            : healthEntries,
        pottyLog: json["pottyLog"] != null
            ? PottyLog.fromJson(json["pottyLog"])
            : pottyLog,
        activityLog: json["activityLog"] != null
            ? ActivityLog.fromJson(json["activityLog"])
            : activityLog,
        photos: json['photos'] != null
            ? (json['photos'] as List)
                .map((json) => CaptionedPhoto.fromJson(json))
                .toList()
            : []);
  }

  @override
  String toString() {
    return "Report for $fullName";
  }
}

1 Ответ

1 голос
/ 28 апреля 2019

В настоящее время мы не поддерживаем "сложные" клавиши в Картах - например, Meal.

Отметить этот номер - https://github.com/dart-lang/json_serializable/issues/396

...