jankuss / genq Goto Github PK
View Code? Open in Web Editor NEWInstant Data Class Generation for Dart
License: MIT License
Instant Data Class Generation for Dart
License: MIT License
Some languages will output json for doubles in a format that will break the current way genq is handling doubles and ints.
Ex:
{
"someDoubleValue": 30.4,
"anotherDoubleValue": 30,
"someIntValue": 30,
}
This will break the deserialization when trying to use a double with "anotherDoubleValue".
Instead of generating the following
bodyFontSize: json['anotherDoubleValue'] == null ? null : json['anotherDoubleValue'] as double?
Follow JsonSerializableGenerator's lead on this and do
(json['anotherDoubleValue'] as num?)?.toDouble()
Similar to how build_runner has a watch to rebuild when files change, is there something similar for genq?
It would be nice if genq could run in editors when saving a file.
Integrations would be good for:
Since genq is sufficiently fast, it should be possible to run genq
before a file is saved, thus making the experience with Hot Reload/Hot Restart seamless.
I work in a very big project and would like to eventually switch most of our data models with a few exceptions from freezed to genq.
However I am running into an issue with json serialization where all properties of genq data models must also be genq models. In a very big project this makes migrating difficult because it will be a big lift to migrate every single data model and even then there are models that need to stay in freezed.
Example:
@Genq(json: true)
class SomeGenqClass with _$SomeGenqClass {
factory SomeGenqClass({
required String value,
required SomeFreezedClass someClass,
}) = _SomeGenqClass;
}
@freezed
class SomeFreezedClass with _$SomeFreezedClass {
const factory SomeFreezedClass({
required String value,
}) = _SomeFreezedClass;
factory SomeFreezedClass.fromJson(Map<String, dynamic> json) =>
_$SomeFreezedClassFromJson(json);
}
Gives an error that The function '$SomeFreezedClassFromJson' isn't defined.
Is there a way around this to make the migration easier?
Thanks
The hashcode function that gets generated cannot handle more than 20 arguments. Therefore once a class reaches over 20 properties this error occurs:
Error: Too many positional arguments: 20 allowed, but 21 found.
Try removing the extra positional arguments.
return Object.hash(
^
org-dartlang-sdk:///third_party/dart/sdk/lib/core/object.dart:183:14: Context: Found this candidate, but the arguments don't match.
static int hash(Object? object1, Object? object2,
The way to fix this is to use
@override
int get hashCode => Object.hashAll([ <List of properties> ]);
instead of
@override
int get hashCode => Object.hash(<List of properties>);
I read through the readme and I'm guessing using the @JsonKey()
annotation with fromJson
and toJson
is the way to parse it.
I did something like this:
//Sample model
@Genq(json: true)
class MyModel with _$MyModel {
factory MyModel({
@JsonKey(
fromJson: GenqDateTime.fromJson,
toJson: GenqDateTime.toJson,
)
required GenqDateTime someDate,
}) = _MyModel ;
}
//toJson fromJson
class GenqDateTime {
final DateTime value;
GenqDateTime(this.value);
static GenqDateTime fromJson(String value) {
final dateTime = DateTime.parse(value);
return GenqDateTime(dateTime);
}
static String toJson(GenqDateTime enclosedDt) {
return enclosedDt.value.toIso8601String();
}
}
I'm just wondering if this is the right way to go about it? I use freezed normally so I got used to how it auto parses Strings into DateTime
objects and just wondering if there's a way to do it without having to have a class enclosing a DateTime
I wanted to make the question more broad for other types but the only type I can think of is DateTime
.
Edit: updated sample code
Right now, it is not possible to define default values for classes. This is due to dart not allowing default values on redirecting constructors.
We should support this, possibly using the same approach as freezed
by using a special annotation (https://pub.dev/packages/freezed#default-values).
It's basically a file watcher detecting when a file contains the @genq
annotations is saved.
I think it would improve the UX developer avoiding us to constantly switch between the Flutter bash and the genq bash
A lot of existing dart code bases use vanilla json_serializable
& json_annotation
(https://pub.dev/packages/json_serializable), without any freezed. For classes marked with the annotation, the fields within the class will be considered for generating the serialization/deserialization code.
We could offer such an annotation, which is almost identical to the annotation from json_serializable
(maybe @GenqJsonSerializable()
). This should make migrations relatively trivial.
A limitation might be that genq has no ability to resolve inherited fields.
Awesome package! Could you adjust it to support const factory constructors?
Ex:
@Genq(json: true)
class User with _$User {
const factory User({
@JsonKey(
fromJson: UserName.fromJson,
toJson: UserName.toJson,
)
required UserName name,
required int age,
}) = _User;
}
Thanks!
Hi!
I just tried your tool and it's very great! I was wondering if it was possible to add a generator command line like in Ruby on Rails
.
It would be something like genq generate User
to generate the user.dart
file with the basic template like in your README.
It would be useful to have this feature because there's no VSCode extension or snippets for that.
Error when parsing: lib\features\auth\entities\app_theme.dart:13
final class AppTheme with _$AppTheme implements ISerializable, ICopyWith {
^
Unexpected token: FINAL (final
). Expected CLASS.
โ Generated 0 data classes
Dart is not JavaScript, we have final, abstract interface, abstract base and sealed classes.
Add ability to generate toJson
/fromJson
methods for data classes.
Currently, Freezed does not support inheritance and there are no plans for it in the future refer to this for context Support Freezed classes extending another Freezed class. #907.
I am curious to know if Genq supports it, as it could be a game-changer.
One change that would make genq an excellent freezed replacement would be to support unions with sealed classes.
Example
@genq
sealed class HomeState with _$HomeState {
const factory HomeState.loading() = LoadingState;
const factory HomeState.loaded(String data) = LoadedState;
const factory HomeState.error(String message) = ErrorState;
}
It would be great if this was able to generate a sealed classes that could be used with dart's pattern matching. Here is more details on how this would be useful:
https://medium.com/@aliammariraq/sealed-classes-in-dart-unlocking-powerful-features-d8dba185925f
Today we use freezed to generate some class methods like this:
import 'package:freezed_annotation/freezed_annotation.dart';
part 'something_state.freezed.dart';
@freezed
class SomethingState with _$SomethingState {
const factory SomethingState.initial() = _Initial;
const factory SomethingState.loading() = _Loading;
const factory SomethingState.invalid(String errorMessage) = _Invalid;
}
// 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 'something_state.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(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');
/// @nodoc
mixin _$SomethingState {
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() loading,
required TResult Function(String errorMessage) invalid,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? initial,
TResult? Function()? loading,
TResult? Function(String errorMessage)? invalid,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? loading,
TResult Function(String errorMessage)? invalid,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_Initial value) initial,
required TResult Function(_Loading value) loading,
required TResult Function(_Invalid value) invalid,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_Initial value)? initial,
TResult? Function(_Loading value)? loading,
TResult? Function(_Invalid value)? invalid,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_Initial value)? initial,
TResult Function(_Loading value)? loading,
TResult Function(_Invalid value)? invalid,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $SomethingStateCopyWith<$Res> {
factory $SomethingStateCopyWith(
SomethingState value, $Res Function(SomethingState) then) =
_$SomethingStateCopyWithImpl<$Res, SomethingState>;
}
/// @nodoc
class _$SomethingStateCopyWithImpl<$Res, $Val extends SomethingState>
implements $SomethingStateCopyWith<$Res> {
_$SomethingStateCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
}
/// @nodoc
abstract class _$$InitialImplCopyWith<$Res> {
factory _$$InitialImplCopyWith(
_$InitialImpl value, $Res Function(_$InitialImpl) then) =
__$$InitialImplCopyWithImpl<$Res>;
}
/// @nodoc
class __$$InitialImplCopyWithImpl<$Res>
extends _$SomethingStateCopyWithImpl<$Res, _$InitialImpl>
implements _$$InitialImplCopyWith<$Res> {
__$$InitialImplCopyWithImpl(
_$InitialImpl _value, $Res Function(_$InitialImpl) _then)
: super(_value, _then);
}
/// @nodoc
class _$InitialImpl implements _Initial {
const _$InitialImpl();
@override
String toString() {
return 'SomethingState.initial()';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType && other is _$InitialImpl);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() loading,
required TResult Function(String errorMessage) invalid,
}) {
return initial();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? initial,
TResult? Function()? loading,
TResult? Function(String errorMessage)? invalid,
}) {
return initial?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? loading,
TResult Function(String errorMessage)? invalid,
required TResult orElse(),
}) {
if (initial != null) {
return initial();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_Initial value) initial,
required TResult Function(_Loading value) loading,
required TResult Function(_Invalid value) invalid,
}) {
return initial(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_Initial value)? initial,
TResult? Function(_Loading value)? loading,
TResult? Function(_Invalid value)? invalid,
}) {
return initial?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_Initial value)? initial,
TResult Function(_Loading value)? loading,
TResult Function(_Invalid value)? invalid,
required TResult orElse(),
}) {
if (initial != null) {
return initial(this);
}
return orElse();
}
}
abstract class _Initial implements SomethingState {
const factory _Initial() = _$InitialImpl;
}
/// @nodoc
abstract class _$$LoadingImplCopyWith<$Res> {
factory _$$LoadingImplCopyWith(
_$LoadingImpl value, $Res Function(_$LoadingImpl) then) =
__$$LoadingImplCopyWithImpl<$Res>;
}
/// @nodoc
class __$$LoadingImplCopyWithImpl<$Res>
extends _$SomethingStateCopyWithImpl<$Res, _$LoadingImpl>
implements _$$LoadingImplCopyWith<$Res> {
__$$LoadingImplCopyWithImpl(
_$LoadingImpl _value, $Res Function(_$LoadingImpl) _then)
: super(_value, _then);
}
/// @nodoc
class _$LoadingImpl implements _Loading {
const _$LoadingImpl();
@override
String toString() {
return 'SomethingState.loading()';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType && other is _$LoadingImpl);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() loading,
required TResult Function(String errorMessage) invalid,
}) {
return loading();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? initial,
TResult? Function()? loading,
TResult? Function(String errorMessage)? invalid,
}) {
return loading?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? loading,
TResult Function(String errorMessage)? invalid,
required TResult orElse(),
}) {
if (loading != null) {
return loading();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_Initial value) initial,
required TResult Function(_Loading value) loading,
required TResult Function(_Invalid value) invalid,
}) {
return loading(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_Initial value)? initial,
TResult? Function(_Loading value)? loading,
TResult? Function(_Invalid value)? invalid,
}) {
return loading?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_Initial value)? initial,
TResult Function(_Loading value)? loading,
TResult Function(_Invalid value)? invalid,
required TResult orElse(),
}) {
if (loading != null) {
return loading(this);
}
return orElse();
}
}
abstract class _Loading implements SomethingState {
const factory _Loading() = _$LoadingImpl;
}
/// @nodoc
abstract class _$$InvalidImplCopyWith<$Res> {
factory _$$InvalidImplCopyWith(
_$InvalidImpl value, $Res Function(_$InvalidImpl) then) =
__$$InvalidImplCopyWithImpl<$Res>;
@useResult
$Res call({String errorMessage});
}
/// @nodoc
class __$$InvalidImplCopyWithImpl<$Res>
extends _$SomethingStateCopyWithImpl<$Res, _$InvalidImpl>
implements _$$InvalidImplCopyWith<$Res> {
__$$InvalidImplCopyWithImpl(
_$InvalidImpl _value, $Res Function(_$InvalidImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? errorMessage = null,
}) {
return _then(_$InvalidImpl(
null == errorMessage
? _value.errorMessage
: errorMessage // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// @nodoc
class _$InvalidImpl implements _Invalid {
const _$InvalidImpl(this.errorMessage);
@override
final String errorMessage;
@override
String toString() {
return 'SomethingState.invalid(errorMessage: $errorMessage)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$InvalidImpl &&
(identical(other.errorMessage, errorMessage) ||
other.errorMessage == errorMessage));
}
@override
int get hashCode => Object.hash(runtimeType, errorMessage);
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$InvalidImplCopyWith<_$InvalidImpl> get copyWith =>
__$$InvalidImplCopyWithImpl<_$InvalidImpl>(this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() loading,
required TResult Function(String errorMessage) invalid,
}) {
return invalid(errorMessage);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? initial,
TResult? Function()? loading,
TResult? Function(String errorMessage)? invalid,
}) {
return invalid?.call(errorMessage);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? loading,
TResult Function(String errorMessage)? invalid,
required TResult orElse(),
}) {
if (invalid != null) {
return invalid(errorMessage);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_Initial value) initial,
required TResult Function(_Loading value) loading,
required TResult Function(_Invalid value) invalid,
}) {
return invalid(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_Initial value)? initial,
TResult? Function(_Loading value)? loading,
TResult? Function(_Invalid value)? invalid,
}) {
return invalid?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_Initial value)? initial,
TResult Function(_Loading value)? loading,
TResult Function(_Invalid value)? invalid,
required TResult orElse(),
}) {
if (invalid != null) {
return invalid(this);
}
return orElse();
}
}
abstract class _Invalid implements SomethingState {
const factory _Invalid(final String errorMessage) = _$InvalidImpl;
String get errorMessage;
@JsonKey(ignore: true)
_$$InvalidImplCopyWith<_$InvalidImpl> get copyWith =>
throw _privateConstructorUsedError;
}
Is it possible to use genq to do the same?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.