Freezed и json_serializable: как использовать собственный конвертер

Я хочу добавить собственный конвертер в замороженный класс, как в этом ответе .

Я пробовал это с помощью этого кода:

      @freezed
class NewsPost with _$NewsPost {
  factory NewsPost({
    @JsonKey(name: "date") @TimestampConverter() DateTime? date,
  }) = _NewsPost;

  factory NewsPost.fromJson(Map<String, dynamic> json) =>
      _$NewsPostFromJson(json);
}

Но не вышло. Любые идеи приветствуются!

Для вашего интереса это мой конвертер:

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

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

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

Спасибо :-)

2 ответа

Поскольку была введена нулевая безопасность, для работы с генератором допускаемость значений NULL для типов, объявленных в JsonConverter необходимо сопоставить допустимость значения NULL для типа в замороженном классе.

Если типы не совпадают, freezed игнорирует преобразователь.

Итак, используя ваш пример:

      @freezed
class NewsPost with _$NewsPost {
  factory NewsPost({
    @TimestampOrNullConverter() DateTime? date, // <-- this is nullable, so the converter needs to handle null
    @TimestampConverter() DateTime createdAt, // <-- not nullable, so your exsiting converter will work
  }) = _NewsPost;

  factory NewsPost.fromJson(Map<String, dynamic> json) =>
      _$NewsPostFromJson(json);
}

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

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

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

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

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

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

Протестировано и работает над flutter 2.5.3 со следующими версиями зависимостей:

      dev_dependencies:
  build_runner: ^2.1.4
  freezed: ^0.15.0+1
  json_serializable: ^5.0.2

Что ж, это не самое элегантное решение, но оно работает.

      @freezed
class NewsPost with _$NewsPost {
  factory NewsPost({
    @JsonKey(
       name: "date", 
       fromJson: dateTimeFromJson, 
       fromJson: dateTimeToJson,
    ) DateTime? date,
  }) = _NewsPost;

  factory NewsPost.fromJson(Map<String, dynamic> json) =>
      _$NewsPostFromJson(json);
}


DateTime dateTimeFromJson(Timestamp timestamp) {
    return timestamp.toDate();
}

Timestamp dateTimeToJson(DateTime date) => Timestamp.fromDate(date);

Думаю, это выход. Используя JsonConverter, я не могу заставить его работать.

Другие вопросы по тегам