diff --git a/build.yaml b/build.yaml new file mode 100644 index 0000000..1571d7c --- /dev/null +++ b/build.yaml @@ -0,0 +1,15 @@ +targets: + $default: + builders: + source_gen|combining_builder: + options: + ignore_for_file: + - type=lint + - implicit_dynamic_parameter + - implicit_dynamic_type + - implicit_dynamic_method + - strict_raw_type + json_serializable: + options: + checked: true + field_rename: snake \ No newline at end of file diff --git a/lib/model/weather_data.dart b/lib/model/weather_data.dart index 97f6069..d41eb0d 100644 --- a/lib/model/weather_data.dart +++ b/lib/model/weather_data.dart @@ -1,37 +1,19 @@ import 'package:flutter_training/model/weather_condition.dart'; -import 'package:flutter_training/utils/extention/enum.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; -class WeatherData { - const WeatherData({ - required this.weatherCondition, - required this.maxTemperature, - required this.minTemperature, - required this.date, - }); +part 'weather_data.freezed.dart'; - factory WeatherData.fromJson(Map json) { - final weatherCondition = WeatherCondition.values - .byNameOrNull(json['weather_condition'].toString()); - if (weatherCondition == null) { - throw const FormatException('Invalid value for [WeatherCondition].'); - } +part 'weather_data.g.dart'; - final maxTemperature = int.parse(json['max_temperature'].toString()); +@freezed +class WeatherData with _$WeatherData { + const factory WeatherData({ + required WeatherCondition weatherCondition, + required int maxTemperature, + required int minTemperature, + required DateTime date, + }) = _WeatherData; - final minTemperature = int.parse(json['min_temperature'].toString()); - - final date = DateTime.parse(json['date']?.toString() ?? ''); - - return WeatherData( - weatherCondition: weatherCondition, - maxTemperature: maxTemperature, - minTemperature: minTemperature, - date: date, - ); - } - - final WeatherCondition weatherCondition; - final int maxTemperature; - final int minTemperature; - final DateTime date; + factory WeatherData.fromJson(Map json) => + _$WeatherDataFromJson(json); } diff --git a/lib/model/weather_data.freezed.dart b/lib/model/weather_data.freezed.dart new file mode 100644 index 0000000..c243c04 --- /dev/null +++ b/lib/model/weather_data.freezed.dart @@ -0,0 +1,219 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'weather_data.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); + +WeatherData _$WeatherDataFromJson(Map json) { + return _WeatherData.fromJson(json); +} + +/// @nodoc +mixin _$WeatherData { + WeatherCondition get weatherCondition => throw _privateConstructorUsedError; + int get maxTemperature => throw _privateConstructorUsedError; + int get minTemperature => throw _privateConstructorUsedError; + DateTime get date => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $WeatherDataCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $WeatherDataCopyWith<$Res> { + factory $WeatherDataCopyWith( + WeatherData value, $Res Function(WeatherData) then) = + _$WeatherDataCopyWithImpl<$Res, WeatherData>; + @useResult + $Res call( + {WeatherCondition weatherCondition, + int maxTemperature, + int minTemperature, + DateTime date}); +} + +/// @nodoc +class _$WeatherDataCopyWithImpl<$Res, $Val extends WeatherData> + implements $WeatherDataCopyWith<$Res> { + _$WeatherDataCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? weatherCondition = null, + Object? maxTemperature = null, + Object? minTemperature = null, + Object? date = null, + }) { + return _then(_value.copyWith( + weatherCondition: null == weatherCondition + ? _value.weatherCondition + : weatherCondition // ignore: cast_nullable_to_non_nullable + as WeatherCondition, + maxTemperature: null == maxTemperature + ? _value.maxTemperature + : maxTemperature // ignore: cast_nullable_to_non_nullable + as int, + minTemperature: null == minTemperature + ? _value.minTemperature + : minTemperature // ignore: cast_nullable_to_non_nullable + as int, + date: null == date + ? _value.date + : date // ignore: cast_nullable_to_non_nullable + as DateTime, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$_WeatherDataCopyWith<$Res> + implements $WeatherDataCopyWith<$Res> { + factory _$$_WeatherDataCopyWith( + _$_WeatherData value, $Res Function(_$_WeatherData) then) = + __$$_WeatherDataCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {WeatherCondition weatherCondition, + int maxTemperature, + int minTemperature, + DateTime date}); +} + +/// @nodoc +class __$$_WeatherDataCopyWithImpl<$Res> + extends _$WeatherDataCopyWithImpl<$Res, _$_WeatherData> + implements _$$_WeatherDataCopyWith<$Res> { + __$$_WeatherDataCopyWithImpl( + _$_WeatherData _value, $Res Function(_$_WeatherData) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? weatherCondition = null, + Object? maxTemperature = null, + Object? minTemperature = null, + Object? date = null, + }) { + return _then(_$_WeatherData( + weatherCondition: null == weatherCondition + ? _value.weatherCondition + : weatherCondition // ignore: cast_nullable_to_non_nullable + as WeatherCondition, + maxTemperature: null == maxTemperature + ? _value.maxTemperature + : maxTemperature // ignore: cast_nullable_to_non_nullable + as int, + minTemperature: null == minTemperature + ? _value.minTemperature + : minTemperature // ignore: cast_nullable_to_non_nullable + as int, + date: null == date + ? _value.date + : date // ignore: cast_nullable_to_non_nullable + as DateTime, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$_WeatherData implements _WeatherData { + const _$_WeatherData( + {required this.weatherCondition, + required this.maxTemperature, + required this.minTemperature, + required this.date}); + + factory _$_WeatherData.fromJson(Map json) => + _$$_WeatherDataFromJson(json); + + @override + final WeatherCondition weatherCondition; + @override + final int maxTemperature; + @override + final int minTemperature; + @override + final DateTime date; + + @override + String toString() { + return 'WeatherData(weatherCondition: $weatherCondition, maxTemperature: $maxTemperature, minTemperature: $minTemperature, date: $date)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_WeatherData && + (identical(other.weatherCondition, weatherCondition) || + other.weatherCondition == weatherCondition) && + (identical(other.maxTemperature, maxTemperature) || + other.maxTemperature == maxTemperature) && + (identical(other.minTemperature, minTemperature) || + other.minTemperature == minTemperature) && + (identical(other.date, date) || other.date == date)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => Object.hash( + runtimeType, weatherCondition, maxTemperature, minTemperature, date); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_WeatherDataCopyWith<_$_WeatherData> get copyWith => + __$$_WeatherDataCopyWithImpl<_$_WeatherData>(this, _$identity); + + @override + Map toJson() { + return _$$_WeatherDataToJson( + this, + ); + } +} + +abstract class _WeatherData implements WeatherData { + const factory _WeatherData( + {required final WeatherCondition weatherCondition, + required final int maxTemperature, + required final int minTemperature, + required final DateTime date}) = _$_WeatherData; + + factory _WeatherData.fromJson(Map json) = + _$_WeatherData.fromJson; + + @override + WeatherCondition get weatherCondition; + @override + int get maxTemperature; + @override + int get minTemperature; + @override + DateTime get date; + @override + @JsonKey(ignore: true) + _$$_WeatherDataCopyWith<_$_WeatherData> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/model/weather_data.g.dart b/lib/model/weather_data.g.dart new file mode 100644 index 0000000..7096a77 --- /dev/null +++ b/lib/model/weather_data.g.dart @@ -0,0 +1,45 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ignore_for_file: type=lint, implicit_dynamic_parameter, implicit_dynamic_type, implicit_dynamic_method, strict_raw_type + +part of 'weather_data.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$_WeatherData _$$_WeatherDataFromJson(Map json) => + $checkedCreate( + r'_$_WeatherData', + json, + ($checkedConvert) { + final val = _$_WeatherData( + weatherCondition: $checkedConvert('weather_condition', + (v) => $enumDecode(_$WeatherConditionEnumMap, v)), + maxTemperature: $checkedConvert('max_temperature', (v) => v as int), + minTemperature: $checkedConvert('min_temperature', (v) => v as int), + date: $checkedConvert('date', (v) => DateTime.parse(v as String)), + ); + return val; + }, + fieldKeyMap: const { + 'weatherCondition': 'weather_condition', + 'maxTemperature': 'max_temperature', + 'minTemperature': 'min_temperature' + }, + ); + +Map _$$_WeatherDataToJson(_$_WeatherData instance) => + { + 'weather_condition': + _$WeatherConditionEnumMap[instance.weatherCondition]!, + 'max_temperature': instance.maxTemperature, + 'min_temperature': instance.minTemperature, + 'date': instance.date.toIso8601String(), + }; + +const _$WeatherConditionEnumMap = { + WeatherCondition.sunny: 'sunny', + WeatherCondition.cloudy: 'cloudy', + WeatherCondition.rainy: 'rainy', +}; diff --git a/lib/model/weather_request.dart b/lib/model/weather_request.dart index 7abd67c..137688f 100644 --- a/lib/model/weather_request.dart +++ b/lib/model/weather_request.dart @@ -1,13 +1,16 @@ -class WeatherRequest { - WeatherRequest({required this.area, required this.date}); - - final String area; - final DateTime date; - - Map toJson() { - return { - 'area': area, - 'date': date.toString(), - }; - } +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'weather_request.freezed.dart'; + +part 'weather_request.g.dart'; + +@freezed +class WeatherRequest with _$WeatherRequest { + const factory WeatherRequest({ + required String area, + required DateTime date, + }) = _WeatherRequest; + + factory WeatherRequest.fromJson(Map json) => + _$WeatherRequestFromJson(json); } diff --git a/lib/model/weather_request.freezed.dart b/lib/model/weather_request.freezed.dart new file mode 100644 index 0000000..ba5cc99 --- /dev/null +++ b/lib/model/weather_request.freezed.dart @@ -0,0 +1,169 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'weather_request.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); + +WeatherRequest _$WeatherRequestFromJson(Map json) { + return _WeatherRequest.fromJson(json); +} + +/// @nodoc +mixin _$WeatherRequest { + String get area => throw _privateConstructorUsedError; + DateTime get date => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $WeatherRequestCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $WeatherRequestCopyWith<$Res> { + factory $WeatherRequestCopyWith( + WeatherRequest value, $Res Function(WeatherRequest) then) = + _$WeatherRequestCopyWithImpl<$Res, WeatherRequest>; + @useResult + $Res call({String area, DateTime date}); +} + +/// @nodoc +class _$WeatherRequestCopyWithImpl<$Res, $Val extends WeatherRequest> + implements $WeatherRequestCopyWith<$Res> { + _$WeatherRequestCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? area = null, + Object? date = null, + }) { + return _then(_value.copyWith( + area: null == area + ? _value.area + : area // ignore: cast_nullable_to_non_nullable + as String, + date: null == date + ? _value.date + : date // ignore: cast_nullable_to_non_nullable + as DateTime, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$_WeatherRequestCopyWith<$Res> + implements $WeatherRequestCopyWith<$Res> { + factory _$$_WeatherRequestCopyWith( + _$_WeatherRequest value, $Res Function(_$_WeatherRequest) then) = + __$$_WeatherRequestCopyWithImpl<$Res>; + @override + @useResult + $Res call({String area, DateTime date}); +} + +/// @nodoc +class __$$_WeatherRequestCopyWithImpl<$Res> + extends _$WeatherRequestCopyWithImpl<$Res, _$_WeatherRequest> + implements _$$_WeatherRequestCopyWith<$Res> { + __$$_WeatherRequestCopyWithImpl( + _$_WeatherRequest _value, $Res Function(_$_WeatherRequest) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? area = null, + Object? date = null, + }) { + return _then(_$_WeatherRequest( + area: null == area + ? _value.area + : area // ignore: cast_nullable_to_non_nullable + as String, + date: null == date + ? _value.date + : date // ignore: cast_nullable_to_non_nullable + as DateTime, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$_WeatherRequest implements _WeatherRequest { + const _$_WeatherRequest({required this.area, required this.date}); + + factory _$_WeatherRequest.fromJson(Map json) => + _$$_WeatherRequestFromJson(json); + + @override + final String area; + @override + final DateTime date; + + @override + String toString() { + return 'WeatherRequest(area: $area, date: $date)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_WeatherRequest && + (identical(other.area, area) || other.area == area) && + (identical(other.date, date) || other.date == date)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => Object.hash(runtimeType, area, date); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_WeatherRequestCopyWith<_$_WeatherRequest> get copyWith => + __$$_WeatherRequestCopyWithImpl<_$_WeatherRequest>(this, _$identity); + + @override + Map toJson() { + return _$$_WeatherRequestToJson( + this, + ); + } +} + +abstract class _WeatherRequest implements WeatherRequest { + const factory _WeatherRequest( + {required final String area, + required final DateTime date}) = _$_WeatherRequest; + + factory _WeatherRequest.fromJson(Map json) = + _$_WeatherRequest.fromJson; + + @override + String get area; + @override + DateTime get date; + @override + @JsonKey(ignore: true) + _$$_WeatherRequestCopyWith<_$_WeatherRequest> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/model/weather_request.g.dart b/lib/model/weather_request.g.dart new file mode 100644 index 0000000..e751d31 --- /dev/null +++ b/lib/model/weather_request.g.dart @@ -0,0 +1,28 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ignore_for_file: type=lint, implicit_dynamic_parameter, implicit_dynamic_type, implicit_dynamic_method, strict_raw_type + +part of 'weather_request.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$_WeatherRequest _$$_WeatherRequestFromJson(Map json) => + $checkedCreate( + r'_$_WeatherRequest', + json, + ($checkedConvert) { + final val = _$_WeatherRequest( + area: $checkedConvert('area', (v) => v as String), + date: $checkedConvert('date', (v) => DateTime.parse(v as String)), + ); + return val; + }, + ); + +Map _$$_WeatherRequestToJson(_$_WeatherRequest instance) => + { + 'area': instance.area, + 'date': instance.date.toIso8601String(), + }; diff --git a/lib/service/weather_service.dart b/lib/service/weather_service.dart index 459a581..009074f 100644 --- a/lib/service/weather_service.dart +++ b/lib/service/weather_service.dart @@ -3,6 +3,7 @@ import 'dart:convert'; import 'package:flutter_training/model/weather_data.dart'; import 'package:flutter_training/model/weather_request.dart'; import 'package:flutter_training/utils/api/result.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:yumemi_weather/yumemi_weather.dart'; class WeatherService { @@ -28,7 +29,9 @@ class WeatherService { YumemiWeatherError.unknown => const Failure('予期せぬエラーが発生しました。') }; - } on FormatException { + } on CheckedFromJsonException catch (_) { + return const Failure('不適切なデータを取得しました。'); + } on FormatException catch (_) { return const Failure('不適切なデータを取得しました。'); } } diff --git a/lib/utils/extention/enum.dart b/lib/utils/extention/enum.dart deleted file mode 100644 index c0b9aa6..0000000 --- a/lib/utils/extention/enum.dart +++ /dev/null @@ -1,16 +0,0 @@ -extension EnumByNameOrNull on Iterable { - /// Finds the enum value in this list with name [name]. - /// - /// Goes through this collection looking for an enum with - /// name [name], as reported by [EnumName.name]. - /// Returns the first value with the given name. - /// If no such value is found, return null. - T? byNameOrNull(String name) { - for (final value in this) { - if (value.name == name) { - return value; - } - } - return null; - } -} diff --git a/pubspec.lock b/pubspec.lock index b466332..9d60dc7 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -259,6 +259,22 @@ packages: description: flutter source: sdk version: "0.0.0" + freezed: + dependency: "direct dev" + description: + name: freezed + sha256: "2df89855fe181baae3b6d714dc3c4317acf4fccd495a6f36e5e00f24144c6c3b" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + freezed_annotation: + dependency: "direct main" + description: + name: freezed_annotation + sha256: c3fd9336eb55a38cc1bbd79ab17573113a8deccd0ecbbf926cca3c62803b5c2d + url: "https://pub.dev" + source: hosted + version: "2.4.1" frontend_server_client: dependency: transitive description: @@ -316,13 +332,21 @@ packages: source: hosted version: "0.6.7" json_annotation: - dependency: transitive + dependency: "direct main" description: name: json_annotation sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 url: "https://pub.dev" source: hosted version: "4.8.1" + json_serializable: + dependency: "direct dev" + description: + name: json_serializable + sha256: aa1f5a8912615733e0fdc7a02af03308933c93235bdc8d50d0b0c8a8ccb0b969 + url: "https://pub.dev" + source: hosted + version: "6.7.1" lints: dependency: transitive description: @@ -448,6 +472,22 @@ packages: description: flutter source: sdk version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: fc0da689e5302edb6177fdd964efcb7f58912f43c28c2047a808f5bfff643d16 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + source_helper: + dependency: transitive + description: + name: source_helper + sha256: "6adebc0006c37dd63fe05bca0a929b99f06402fc95aa35bf36d67f5c06de01fd" + url: "https://pub.dev" + source: hosted + version: "1.3.4" source_span: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 7dd6165..6150b08 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -12,6 +12,8 @@ dependencies: flutter_svg: ^2.0.7 + freezed_annotation: ^2.4.1 + json_annotation: ^4.8.1 yumemi_weather: git: url: https://github.com/yumemi-inc/flutter-training-template.git @@ -25,6 +27,8 @@ dev_dependencies: build_runner: ^2.4.6 flutter_gen_runner: ^5.3.1 + freezed: ^2.4.1 + json_serializable: ^6.7.1 flutter_gen: integrations: