当前位置: 首页 > 知识库问答 >
问题:

如何解析类型“时间戳”不是类型转换中类型“字符串”的子类型

蒋茂
2023-03-14

我想从Firestore获取会议并将其映射到以下会议模型中:

part 'meeting.g.dart';

@JsonSerializable(explicitToJson: true)
class Meeting {
  String id;
  DateTime date;

  Meeting(this.id, this.date);

  factory Meeting.fromJson(Map<String, dynamic> json) {

    return _$MeetingFromJson(json);
  }

  Map<String, dynamic> toJson() => _$MeetingToJson(this);
}

从Firestore获取文档,然后在iterable上调用< code>fromJson,但会引发一个异常:

type 'Timestamp' is not a subtype of type 'String' in type cast

当我进入生成的< code>meeting.g.dart时,就是这一行导致了错误

json['date'] == null ? null : DateTime.parse(json['date'] as String)

为了解决此问题,我尝试在模型中从 DateTime 更改为 Timestamp,但随后显示以下生成错误:

Error running JsonSerializableGenerator
Could not generate `fromJson` code for `date`.
None of the provided `TypeHelper` instances support the defined type.

你能告诉我你如何解决这个问题吗?有没有另一种首选方法可以使用json_serializable进行JSON序列化来组合Firebase和Flutter项目?也许甚至可以取代json_serializable的用法?

共有3个答案

戚哲
2023-03-14

使用toJsonfromJsonconverter函数,如下例所示:https://github.com/dart-lang/json_serializable/blob/master/example/lib/example.dart

该解决方案的好处是您不必对属性名称进行硬编码

在阅读了https://github.com/dart-lang/json_serializable/issues/351,的文章后,我修改了< code>Meeting.fromJson,现在它可以正常工作了:

  factory Meeting.fromJson(Map<String, dynamic> json) {
    json["date"] = ((json["date"] as Timestamp).toDate().toString());
    return _$MeetingFromJson(json);
  }

json["date"]Timestamp默认情况下,我将其转换为String,在它到达生成的反序列化程序之前,因此当它尝试将json["date"]转换为String时不会崩溃

虽然,我不太喜欢这个解决方法,因为我必须硬编码属性的名称和耦合类型,但就目前而言,这个解决方案已经足够好了。

另一种选择是尝试https://pub.dev/packages/built_valueseraliazion,这是在他们的博客中推荐的https://flutter.dev/docs/development/data-and-backend/json

翟永春
2023-03-14

感谢@Reed,指明了正确的方向。当将< code>DateTime值传递给< code>FireStore时,firebase将该值作为< code>Timestamp似乎没有问题,但是在取回该值时,需要对其进行适当的处理。不管怎样,这是一个双向的例子:

import 'package:cloud_firestore/cloud_firestore.dart'; //<-- dependency referencing Timestamp
import 'package:json_annotation/json_annotation.dart';

part 'test_date.g.dart';

@JsonSerializable(anyMap: true)
class TestDate {

  @JsonKey(fromJson: _dateTimeFromTimestamp, toJson: _dateTimeAsIs)
  final DateTime theDate; 


  TestDate({this.theDate,});

   factory TestDate.fromJson(Map<String, dynamic> json) {     
     return _$TestDateFromJson(json);
   } 
  Map<String, dynamic> toJson() => _$TestDateToJson(this);

  static DateTime _dateTimeAsIs(DateTime dateTime) => dateTime;  //<-- pass through no need for generated code to perform any formatting

// https://stackoverflow.com/questions/56627888/how-to-print-firestore-timestamp-as-formatted-date-and-time-in-flutter
  static DateTime _dateTimeFromTimestamp(Timestamp timestamp) {
    return DateTime.parse(timestamp.toDate().toString());
  }
}
查宜修
2023-03-14

使用JsonConverter

class TimestampConverter implements JsonConverter<DateTime, Timestamp> {
  const TimestampConverter();

  @override
  DateTime fromJson(Timestamp timestamp) {
    return timestamp.toDate();
  }

  @override
  Timestamp toJson(DateTime date) => Timestamp.fromDate(date);
}

@JsonSerializable()
class User{
  final String id;
  @TimestampConverter()
  final DateTime timeCreated;

  User([this.id, this.timeCreated]);

  factory User.fromSnapshot(DocumentSnapshot documentSnapshot) =>
      _$UserFromJson(
          documentSnapshot.data..["_id"] = documentSnapshot.documentID);

  Map<String, dynamic> toJson() => _$UserToJson(this)..remove("_id");
}
 类似资料: