Код дротика не генерируется должным образом при использовании расширений - PullRequest
0 голосов
/ 07 января 2020

У меня есть два приложения Dart - на стороне сервера и Angular клиент Dart. Оба используют одинаковые зависимости от json_annotation: ^3.0.0 и json_serializable: ^3.2.2. Теперь с Dart SDK 2.7.0 можно использовать тип extension. У меня очень одинаковое расширение в обоих приложениях для DateTime, которое добавляет геттер quarter. Оба приложения используют DateTimeConverter, который преобразует DateTime в String и наоборот. Поскольку я добавил расширение в клиентское приложение, код, сгенерированный json serializable, не вызывает конвертер. Но он все еще генерируется в серверном приложении. Я не понимаю почему. Единственные отличия в других пакетах: c для каждого приложения (angular дротик, html, ... для клиентского приложения и акведука, postgres, ... для серверного приложения).

Когда я удаляю расширение на клиенте, сгенерированный код содержит вызовы конвертера.

Пока я могу исправить код, чтобы не использовать расширение, но я бы хотел используй это. Кто-нибудь знает как это исправить или где проблема?

client/lib/src/extension/datetime_ext.dart, server/lib/src/extension/datetime_ext.dart

extension DateTimeExt on DateTime {
    int get quarter => month <= 3 ? 1 : month <= 6 ? 2 : month <= 9 ? 3 : month <= 12 ? 4 : -1;
}

client/lib/src/converter/datetime_conv.dart, server/lib/src/converter/datetime_conv.dart

import 'package:json_annotation/json_annotation.dart';

///
///  DateTimeConverter annotation
///  If the datetime is already of DateTime type return it, otherwise try to parse String.
///  It's handy when processing JSON-like Map where datetime is already preprocessed by caller (e.g. database driver)
///  e.g.
///  @JsonKey(name: 'date')
///  @DateTimeConverter()
///  DateTime date;
///
class DateTimeConverter implements JsonConverter<DateTime, Object> {

    const DateTimeConverter();

    // DateTimes can represent time values that are at a distance of at most 100,000,000
    // days from epoch (1970-01-01 UTC): -271821-04-20 to 275760-09-13.
    static DateTime minDateTime = DateTime.utc(-271821,04,20);
    static DateTime maxDateTime = DateTime.utc(275760,09,13);

    @override
    DateTime fromJson(Object json) {
        if(json == null) {
            return null;
        } else if(json is DateTime) {
            return json;
        } else if(json is String) {
            if(json == '-infinity') {
                return minDateTime;
            } else if(json == 'infinity') {
                return maxDateTime;
            } else {
                return DateTime.parse(json);
            }
        } else {
            return null;
        }
    }

    @override
    String toJson(DateTime datetime) {
        if(datetime == minDateTime) {
            return '-infinity';
        } else if(datetime == maxDateTime) {
            return 'infinity';
        } else {
            return datetime?.toIso8601String();
        }
    }
}

client/pubspec.yaml, server/pubspec.yaml

environment:
  sdk: ">=2.7.0 <3.0.0"

dependencies:
  ...
  json_annotation: ^3.0.0
  ...
dev_dependencies:
  build_runner: ^1.7.2
  json_serializable: ^3.2.2
  ...

класс модели на клиенте client/lib/src/model/energy.dart

import 'package:json_annotation/json_annotation.dart';
import 'package:client/src/converter/datetime_conv.dart';
part 'energy.g.dart';

@JsonSerializable(includeIfNull: false)
class Energy {
  Energy();
  factory Energy.fromJson(Map<String, dynamic> json) => _$EnergyFromJson(json);
  Map<String, dynamic> toJson() => _$EnergyToJson(this);

  @JsonKey(name: 'id')
  int id;
  @JsonKey(name: 'energy')
  String energy;
  @JsonKey(name: 'date_from')
  @DateTimeConverter()
  DateTime dateFrom;
  @JsonKey(name: 'vat_rate')
  int vatRate;
}

сгенерированный client/lib/src/model/energy.g.dart

part of 'energy.dart';
Energy _$EnergyFromJson(Map<String, dynamic> json) {
  return Energy()
    ..id = json['id'] as int
    ..energy = json['energy'] as String
    ..dateFrom = json['date_from'] // !!! DateTimeConverter() missing
    ..vatRate = json['vat_rate'] as int;
}

Map<String, dynamic> _$EnergyToJson(Energy instance) {
  final val = <String, dynamic>{};

  void writeNotNull(String key, dynamic value) {
    if (value != null) {
      val[key] = value;
    }
  }
  writeNotNull('id', instance.id);
  writeNotNull('energy', instance.energy);
  writeNotNull('date_from', instance.dateFrom);  // !!! DateTimeConverter() missing
  writeNotNull('vat_rate', instance.vatRate);
  return val;
}

класс модели на сервере server/lib/src/model/energy.dart

import 'package:json_annotation/json_annotation.dart';
import 'package:server/src/converter/datetime_conv.dart';
import 'model.dart';
part 'energy.g.dart';

@JsonSerializable(includeIfNull: false)
class Energy extends Model {
  Energy();
  factory Energy.fromJson(Map<String, dynamic> json) => _$EnergyFromJson(json);
  Map<String, dynamic> toJson() => _$EnergyToJson(this);

  @JsonKey(name: 'id')
  int id;
  @JsonKey(name: 'energy')
  String energy;
  @JsonKey(name: 'date_from')
  @DateTimeConverter()
  DateTime dateFrom;
  @JsonKey(name: 'vat_rate')
  int vatRate;

  // Aqueduct serializable implementation (inherited from Model)
  @override
  Map<String, dynamic> asMap() {
    return _$EnergyToJson(this);
  }

  @override
  void readFromMap(Map<String, dynamic> object) {
  }
}

сгенерировано server/lib/src/model/energy.g.dart с вызовами на DateTimeConverter

part of 'energy.dart';

Energy _$EnergyFromJson(Map<String, dynamic> json) {
  return Energy()
    ..id = json['id'] as int
    ..energy = json['energy'] as String
    ..dateFrom = const DateTimeConverter().fromJson(json['date_from'])
    ..vatRate = json['vat_rate'] as int;
}

Map<String, dynamic> _$EnergyToJson(Energy instance) {
  final val = <String, dynamic>{};

  void writeNotNull(String key, dynamic value) {
    if (value != null) {
      val[key] = value;
    }
  }

  writeNotNull('id', instance.id);
  writeNotNull('energy', instance.energy);
  writeNotNull(
      'date_from', const DateTimeConverter().toJson(instance.dateFrom));
  writeNotNull('vat_rate', instance.vatRate);
  return val;
}
...