У меня есть два приложения 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;
}