[dart][dart-dio] Add built_value date support w/o timemachine (#9180)

* [dart][dart-dio] Add built_value date support w/o timemachine

* Test improvements

* Fix lists of dates not working
This commit is contained in:
Peter Leibiger 2021-04-13 10:52:27 +02:00 committed by GitHub
parent 7a1f7b2270
commit b4ea00ed42
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 292 additions and 25 deletions

View File

@ -205,13 +205,19 @@ public class DartDioNextClientCodegen extends AbstractDartCodegen {
imports.put("OffsetDate", "package:time_machine/time_machine.dart");
imports.put("OffsetDateTime", "package:time_machine/time_machine.dart");
if (SERIALIZATION_LIBRARY_BUILT_VALUE.equals(library)) {
supportingFiles.add(new SupportingFile("serialization/built_value/local_date_serializer.mustache", srcFolder, "local_date_serializer.dart"));
supportingFiles.add(new SupportingFile("serialization/built_value/offset_date_serializer.mustache", srcFolder, "local_date_serializer.dart"));
}
break;
default:
case DATE_LIBRARY_CORE:
// this option uses the dart core classes
additionalProperties.put("useDateLibCore", "true");
if (SERIALIZATION_LIBRARY_BUILT_VALUE.equals(library)) {
typeMapping.put("date", "Date");
typeMapping.put("Date", "Date");
importMapping.put("Date", "package:" + pubName + "/src/model/date.dart");
supportingFiles.add(new SupportingFile("serialization/built_value/date.mustache", srcFolder + File.separator + "model", "date.dart"));
supportingFiles.add(new SupportingFile("serialization/built_value/date_serializer.mustache", srcFolder, "date_serializer.dart"));
}
break;
}
}

View File

@ -3,7 +3,8 @@ export 'package:{{pubName}}/src/api.dart';
export 'package:{{pubName}}/src/auth/api_key_auth.dart';
export 'package:{{pubName}}/src/auth/basic_auth.dart';
export 'package:{{pubName}}/src/auth/oauth.dart';
{{#useBuiltValue}}export 'package:{{pubName}}/src/serializers.dart';{{/useBuiltValue}}
{{#useBuiltValue}}export 'package:{{pubName}}/src/serializers.dart';
{{#useDateLibCore}}export 'package:{{pubName}}/src/model/date.dart';{{/useDateLibCore}}{{/useBuiltValue}}
{{#apiInfo}}{{#apis}}export 'package:{{pubName}}/src/api/{{classFilename}}.dart';
{{/apis}}{{/apiInfo}}

View File

@ -0,0 +1,69 @@
/// A gregorian calendar date generated by
/// OpenAPI generator to differentiate
/// between [DateTime] and [Date] formats.
class Date implements Comparable<Date> {
final int year;
/// January is 1.
final int month;
/// First day is 1.
final int day;
Date(this.year, this.month, this.day);
/// The current date
static Date now({bool utc = false}) {
var now = DateTime.now();
if (utc) {
now = now.toUtc();
}
return now.toDate();
}
/// Convert to a [DateTime].
DateTime toDateTime({bool utc = false}) {
if (utc) {
DateTime.utc(year, month, day);
}
return DateTime(year, month, day);
}
@override
int compareTo(Date other) {
int d = year.compareTo(other.year);
if (d != 0) {
return d;
}
d = month.compareTo(other.month);
if (d != 0) {
return d;
}
return day.compareTo(other.day);
}
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is Date &&
runtimeType == other.runtimeType &&
year == other.year &&
month == other.month &&
day == other.day;
@override
int get hashCode => year.hashCode ^ month.hashCode ^ day.hashCode;
@override
String toString() {
final yyyy = year.toString();
final mm = month.toString().padLeft(2, '0');
final dd = day.toString().padLeft(2, '0');
return '$yyyy-$mm-$dd';
}
}
extension DateTimeToDate on DateTime {
Date toDate() => Date(year, month, day);
}

View File

@ -0,0 +1,28 @@
{{>header}}
import 'package:built_collection/built_collection.dart';
import 'package:built_value/serializer.dart';
import 'package:{{pubName}}/src/model/date.dart';
class DateSerializer implements PrimitiveSerializer<Date> {
const DateSerializer();
@override
Iterable<Type> get types => BuiltList.of([Date]);
@override
String get wireName => 'Date';
@override
Date deserialize(Serializers serializers, Object serialized,
{FullType specifiedType = FullType.unspecified}) {
final parsed = DateTime.parse(serialized as String);
return Date(parsed.year, parsed.month, parsed.day);
}
@override
Object serialize(Serializers serializers, Date date,
{FullType specifiedType = FullType.unspecified}) {
return date.toString();
}
}

View File

@ -8,7 +8,7 @@ class OffsetDateSerializer implements PrimitiveSerializer<OffsetDate> {
const OffsetDateSerializer();
@override
Iterable<Type> get types => BuiltList<Type>([OffsetDate]);
Iterable<Type> get types => BuiltList.of([OffsetDate]);
@override
String get wireName => 'OffsetDate';

View File

@ -1,11 +1,15 @@
{{>header}}
// ignore_for_file: unused_import
import 'package:built_collection/built_collection.dart';
import 'package:built_value/json_object.dart';
import 'package:built_value/serializer.dart';
import 'package:built_value/standard_json_plugin.dart';
{{#useDateLibCore}}import 'package:built_value/iso_8601_date_time_serializer.dart';{{/useDateLibCore}}
{{#useDateLibCore}}import 'package:built_value/iso_8601_date_time_serializer.dart';
import 'package:{{pubName}}/src/date_serializer.dart';
import 'package:{{pubName}}/src/model/date.dart';{{/useDateLibCore}}
{{#useDateLibTimeMachine}}import 'package:time_machine/time_machine.dart';
import 'package:{{pubName}}/src/local_date_serializer.dart';{{/useDateLibTimeMachine}}
import 'package:{{pubName}}/src/offset_date_serializer.dart';{{/useDateLibTimeMachine}}
{{#models}}{{#model}}import 'package:{{pubName}}/src/model/{{classFilename}}.dart';
{{/model}}{{/models}}
part 'serializers.g.dart';
@ -25,8 +29,9 @@ Serializers serializers = (_$serializers.toBuilder(){{#apiInfo}}{{#apis}}{{#seri
{{/isMap}}
){{/serializers}}{{/apis}}{{/apiInfo}}{{#useDateLibTimeMachine}}
..add(const OffsetDateSerializer())
..add(const OffsetDateTimeSerializer()){{/useDateLibTimeMachine}}
..add(Iso8601DateTimeSerializer()))
..add(const OffsetDateTimeSerializer()){{/useDateLibTimeMachine}}{{#useDateLibCore}}
..add(const DateSerializer())
..add(Iso8601DateTimeSerializer())){{/useDateLibCore}}
.build();
Serializers standardSerializers =

View File

@ -66,6 +66,7 @@ lib/src/auth/api_key_auth.dart
lib/src/auth/auth.dart
lib/src/auth/basic_auth.dart
lib/src/auth/oauth.dart
lib/src/date_serializer.dart
lib/src/model/additional_properties_class.dart
lib/src/model/animal.dart
lib/src/model/api_response.dart
@ -77,6 +78,7 @@ lib/src/model/cat.dart
lib/src/model/cat_all_of.dart
lib/src/model/category.dart
lib/src/model/class_model.dart
lib/src/model/date.dart
lib/src/model/dog.dart
lib/src/model/dog_all_of.dart
lib/src/model/enum_arrays.dart

View File

@ -478,7 +478,7 @@ var int64 = 789; // int | None
var float = 3.4; // double | None
var string = string_example; // String | None
var binary = BINARY_DATA_HERE; // Uint8List | None
var date = 2013-10-20; // DateTime | None
var date = 2013-10-20; // Date | None
var dateTime = 2013-10-20T19:20:30+01:00; // DateTime | None
var password = password_example; // String | None
var callback = callback_example; // String | None
@ -504,7 +504,7 @@ Name | Type | Description | Notes
**float** | **double**| None | [optional]
**string** | **String**| None | [optional]
**binary** | **Uint8List**| None | [optional]
**date** | **DateTime**| None | [optional]
**date** | **Date**| None | [optional]
**dateTime** | **DateTime**| None | [optional]
**password** | **String**| None | [optional]
**callback** | **String**| None | [optional]

View File

@ -18,7 +18,7 @@ Name | Type | Description | Notes
**string** | **String** | | [optional]
**byte** | **String** | |
**binary** | [**Uint8List**](Uint8List.md) | | [optional]
**date** | [**DateTime**](DateTime.md) | |
**date** | [**Date**](Date.md) | |
**dateTime** | [**DateTime**](DateTime.md) | | [optional]
**uuid** | **String** | | [optional]
**password** | **String** | |

View File

@ -12,7 +12,7 @@ Name | Type | Description | Notes
**numberProp** | **num** | | [optional]
**booleanProp** | **bool** | | [optional]
**stringProp** | **String** | | [optional]
**dateProp** | [**DateTime**](DateTime.md) | | [optional]
**dateProp** | [**Date**](Date.md) | | [optional]
**datetimeProp** | [**DateTime**](DateTime.md) | | [optional]
**arrayNullableProp** | [**BuiltList<JsonObject>**](JsonObject.md) | | [optional]
**arrayAndItemsNullableProp** | [**BuiltList<JsonObject>**](JsonObject.md) | | [optional]

View File

@ -7,6 +7,7 @@ export 'package:openapi/src/auth/api_key_auth.dart';
export 'package:openapi/src/auth/basic_auth.dart';
export 'package:openapi/src/auth/oauth.dart';
export 'package:openapi/src/serializers.dart';
export 'package:openapi/src/model/date.dart';
export 'package:openapi/src/api/another_fake_api.dart';
export 'package:openapi/src/api/default_api.dart';

View File

@ -10,6 +10,7 @@ import 'package:dio/dio.dart';
import 'dart:typed_data';
import 'package:built_collection/built_collection.dart';
import 'package:openapi/src/api_util.dart';
import 'package:openapi/src/model/date.dart';
import 'package:openapi/src/model/file_schema_test_class.dart';
import 'package:openapi/src/model/health_check_result.dart';
import 'package:openapi/src/model/model_client.dart';
@ -826,7 +827,7 @@ class FakeApi {
double? float,
String? string,
Uint8List? binary,
DateTime? date,
Date? date,
DateTime? dateTime,
String? password,
String? callback,
@ -875,7 +876,7 @@ class FakeApi {
r'pattern_without_delimiter': encodeFormParameter(_serializers, patternWithoutDelimiter, const FullType(String)),
r'byte': encodeFormParameter(_serializers, byte, const FullType(String)),
if (binary != null) r'binary': MultipartFile.fromBytes(binary, filename: r'binary'),
if (date != null) r'date': encodeFormParameter(_serializers, date, const FullType(DateTime)),
if (date != null) r'date': encodeFormParameter(_serializers, date, const FullType(Date)),
if (dateTime != null) r'dateTime': encodeFormParameter(_serializers, dateTime, const FullType(DateTime)),
if (password != null) r'password': encodeFormParameter(_serializers, password, const FullType(String)),
if (callback != null) r'callback': encodeFormParameter(_serializers, callback, const FullType(String)),

View File

@ -0,0 +1,31 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
import 'package:built_collection/built_collection.dart';
import 'package:built_value/serializer.dart';
import 'package:openapi/src/model/date.dart';
class DateSerializer implements PrimitiveSerializer<Date> {
const DateSerializer();
@override
Iterable<Type> get types => BuiltList.of([Date]);
@override
String get wireName => 'Date';
@override
Date deserialize(Serializers serializers, Object serialized,
{FullType specifiedType = FullType.unspecified}) {
final parsed = DateTime.parse(serialized as String);
return Date(parsed.year, parsed.month, parsed.day);
}
@override
Object serialize(Serializers serializers, Date date,
{FullType specifiedType = FullType.unspecified}) {
return date.toString();
}
}

View File

@ -0,0 +1,69 @@
/// A gregorian calendar date generated by
/// OpenAPI generator to differentiate
/// between [DateTime] and [Date] formats.
class Date implements Comparable<Date> {
final int year;
/// January is 1.
final int month;
/// First day is 1.
final int day;
Date(this.year, this.month, this.day);
/// The current date
static Date now({bool utc = false}) {
var now = DateTime.now();
if (utc) {
now = now.toUtc();
}
return now.toDate();
}
/// Convert to a [DateTime].
DateTime toDateTime({bool utc = false}) {
if (utc) {
DateTime.utc(year, month, day);
}
return DateTime(year, month, day);
}
@override
int compareTo(Date other) {
int d = year.compareTo(other.year);
if (d != 0) {
return d;
}
d = month.compareTo(other.month);
if (d != 0) {
return d;
}
return day.compareTo(other.day);
}
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is Date &&
runtimeType == other.runtimeType &&
year == other.year &&
month == other.month &&
day == other.day;
@override
int get hashCode => year.hashCode ^ month.hashCode ^ day.hashCode;
@override
String toString() {
final yyyy = year.toString();
final mm = month.toString().padLeft(2, '0');
final dd = day.toString().padLeft(2, '0');
return '$yyyy-$mm-$dd';
}
}
extension DateTimeToDate on DateTime {
Date toDate() => Date(year, month, day);
}

View File

@ -3,6 +3,7 @@
//
import 'dart:typed_data';
import 'package:openapi/src/model/date.dart';
import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
@ -42,7 +43,7 @@ abstract class FormatTest implements Built<FormatTest, FormatTestBuilder> {
Uint8List? get binary;
@BuiltValueField(wireName: r'date')
DateTime get date;
Date get date;
@BuiltValueField(wireName: r'dateTime')
DateTime? get dateTime;
@ -141,7 +142,7 @@ class _$FormatTestSerializer implements StructuredSerializer<FormatTest> {
result
..add(r'date')
..add(serializers.serialize(object.date,
specifiedType: const FullType(DateTime)));
specifiedType: const FullType(Date)));
if (object.dateTime != null) {
result
..add(r'dateTime')
@ -226,7 +227,7 @@ class _$FormatTestSerializer implements StructuredSerializer<FormatTest> {
break;
case r'date':
result.date = serializers.deserialize(value,
specifiedType: const FullType(DateTime)) as DateTime;
specifiedType: const FullType(Date)) as Date;
break;
case r'dateTime':
result.dateTime = serializers.deserialize(value,

View File

@ -3,6 +3,7 @@
//
import 'package:built_collection/built_collection.dart';
import 'package:openapi/src/model/date.dart';
import 'package:built_value/json_object.dart';
import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
@ -25,7 +26,7 @@ abstract class NullableClass implements Built<NullableClass, NullableClassBuilde
String? get stringProp;
@BuiltValueField(wireName: r'date_prop')
DateTime? get dateProp;
Date? get dateProp;
@BuiltValueField(wireName: r'datetime_prop')
DateTime? get datetimeProp;
@ -97,7 +98,7 @@ class _$NullableClassSerializer implements StructuredSerializer<NullableClass> {
result
..add(r'date_prop')
..add(serializers.serialize(object.dateProp,
specifiedType: const FullType(DateTime)));
specifiedType: const FullType(Date)));
}
if (object.datetimeProp != null) {
result
@ -173,7 +174,7 @@ class _$NullableClassSerializer implements StructuredSerializer<NullableClass> {
break;
case r'date_prop':
result.dateProp = serializers.deserialize(value,
specifiedType: const FullType(DateTime)) as DateTime;
specifiedType: const FullType(Date)) as Date;
break;
case r'datetime_prop':
result.datetimeProp = serializers.deserialize(value,

View File

@ -2,11 +2,15 @@
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// ignore_for_file: unused_import
import 'package:built_collection/built_collection.dart';
import 'package:built_value/json_object.dart';
import 'package:built_value/serializer.dart';
import 'package:built_value/standard_json_plugin.dart';
import 'package:built_value/iso_8601_date_time_serializer.dart';
import 'package:openapi/src/date_serializer.dart';
import 'package:openapi/src/model/date.dart';
import 'package:openapi/src/model/additional_properties_class.dart';
import 'package:openapi/src/model/animal.dart';
@ -122,6 +126,7 @@ Serializers serializers = (_$serializers.toBuilder()
const FullType(BuiltList, [FullType(User)]),
() => ListBuilder<User>(),
)
..add(const DateSerializer())
..add(Iso8601DateTimeSerializer()))
.build();

View File

@ -81,7 +81,7 @@ void main() {
//
// Fake endpoint for testing various parameters
//
//Future testEndpointParameters(num number, double double_, String patternWithoutDelimiter, String byte, { int integer, int int32, int int64, double float, String string, Uint8List binary, DateTime date, DateTime dateTime, String password, String callback }) async
//Future testEndpointParameters(num number, double double_, String patternWithoutDelimiter, String byte, { int integer, int int32, int int64, double float, String string, Uint8List binary, Date date, DateTime dateTime, String password, String callback }) async
test('test testEndpointParameters', () async {
// TODO
});

View File

@ -57,7 +57,7 @@ void main() {
// TODO
});
// DateTime date
// Date date
test('to test the property `date`', () async {
// TODO
});

View File

@ -27,7 +27,7 @@ void main() {
// TODO
});
// DateTime dateProp
// Date dateProp
test('to test the property `dateProp`', () async {
// TODO
});

View File

@ -34,7 +34,7 @@ void main() {
'integer': '45',
'int32': '2147483647',
'int64': '9223372036854775807',
'date': '2020-08-11T00:00:00.000Z',
'date': '2020-08-11',
'dateTime': '2020-08-11T12:30:55.123Z',
'binary': "Instance of 'MultipartFile'",
},
@ -53,7 +53,7 @@ void main() {
integer: 45,
int32: 2147483647,
int64: 9223372036854775807,
date: DateTime.utc(2020, 8, 11),
date: Date(2020, 8, 11),
dateTime: DateTime.utc(2020, 8, 11, 12, 30, 55, 123),
binary: Uint8List.fromList([0, 1, 2, 3, 4, 5]),
);

View File

@ -0,0 +1,22 @@
import 'package:openapi/openapi.dart';
import 'package:openapi/src/date_serializer.dart';
import 'package:test/test.dart';
void main() {
final date1 = Date(1999, 3, 25);
const serializer = DateSerializer();
group(DateSerializer, () {
test('serialize', () {
expect(serializer.serialize(serializers, date1), '1999-03-25');
});
test('deserialize date', () {
expect(serializer.deserialize(serializers, '1999-03-25'), date1);
});
test('deserialize ISO', () {
expect(serializer.deserialize(serializers, '1999-03-25T12:30:55.123Z'), date1);
});
});
}

View File

@ -0,0 +1,25 @@
import 'package:openapi/openapi.dart';
import 'package:test/test.dart';
void main() {
final date1 = Date(1999, 3, 25);
final date2 = Date(1999, 1, 1);
group(Date, () {
test('toString', () {
expect(date1.toString(), '1999-03-25');
});
test('compare >', () {
expect(date1.compareTo(date2), 1);
});
test('compare <', () {
expect(date2.compareTo(date1), -1);
});
test('compare =', () {
expect(date1.compareTo(date1), 0);
});
});
}