dart freezed default for empty class - flutter

#freezed
class ABCModel with _$ABCModel {
factory ABCModel({
#JsonKey(name: "id") #Default('') String id,
#JsonKey(name: "name") #Default('') String name,
}) = _ABCModel;
factory ABCModel.fromJson(Map<String, dynamic> json) => _$ABCModelFromJson(json);
}
#freezed
class EFGModel with _$EFGModel {
factory EFGModel({
#JsonKey(name: "abc") #Default(ABCModel()) ABCModel abc, //empty ABCModel
}) = _EFGModel;
factory EFGModel.fromJson(Map<String, dynamic> json) => _$EFGModelFromJson(json);
}
If EFGModel get an empty or null abc json value, what is the suitable value to put on #Default() freezed annotation, #Default(ABCModel()) is not correct

Note the Player.blank() constructor below. Like this...
#freezed
class Player with _$Player {
Player._();
factory Player({
#Default('') String handle,
#Default('') String realname,
Contact? contactinfo,
#Default(false) bool emailverified,
#Default(false) bool showemail,
#Default(false) bool showphone,
#Default('') String avatarurl,
DateTime? datejoined,
#Default(0) int transactions,
DateTime? datelasttransaction,
DateTime? datelastlogin,
#Default([]) List<String> tags,
#Default([]) List<String> leagues,
#Default([]) List<String> events,
#Default(0) int views,
#Default(0) int likes,
#Default(0) int loginfails,
#JsonKey(ignore: true) #Default('') String password,
#JsonKey(ignore: true) #Default('') String confirm,
required Meta meta,
}) = _Player;
factory Player.blank() => Player(contactinfo: Contact(), meta: Meta());
factory Player.fromJson(Map<String, dynamic> json) => _$PlayerFromJson(json);

Related

Non-nullable instance field 'id' must be initialized. Try adding an initializer expression, or add a field initializer in this constructor,

How to Solve Error: Non-nullable instance field 'id' must be initialized.
Try adding an initializer expression, or add a field initializer in this constructor, or mark it 'late'.
class CategoryModel {
int id;
String name;
CategoryModel({
required this.id,
required this.name,
});
CategoryModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
}
If your field (id, name e.g.) CANNOT be null at anytime, add required keyword.
class CategoryModel {
final int id;
final String name;
CategoryModel({
required this.id,
required this.name,
});
CategoryModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
}
If your field CAN be null, make it nullable by adding ? and it doesn't need to be required field.
class CategoryModel {
final int? id;
final String? name;
CategoryModel({
this.id,
this.name,
});
CategoryModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
}

Flutter Model from reqres.in

i read code somewhere from github and see 3 models here. this code should be use form get,post,put and delete but before go to far i dont understand why he separate 3 models. maybe someone can explain me what this person thingking. this is the models
user.dart
import 'package:json_annotation/json_annotation.dart';
import 'data.dart';
part 'user.g.dart';
#JsonSerializable()
class User {
User({
required this.data,
});
Data data;
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}
this is user_info.dart
import 'package:json_annotation/json_annotation.dart';
part 'user_info.g.dart';
#JsonSerializable()
class UserInfo {
String name;
String job;
String? id;
String? createdAt;
String? updatedAt;
UserInfo({
required this.name,
required this.job,
this.id,
this.createdAt,
this.updatedAt,
});
factory UserInfo.fromJson(Map<String, dynamic> json) =>
_$UserInfoFromJson(json);
Map<String, dynamic> toJson() => _$UserInfoToJson(this);
}
this is data.dart
import 'package:json_annotation/json_annotation.dart';
part 'data.g.dart';
#JsonSerializable()
class Data {
Data({
required this.id,
required this.email,
required this.firstName,
required this.lastName,
required this.avatar,
});
int id;
String email;
#JsonKey(name: 'first_name')
String firstName;
#JsonKey(name: 'last_name')
String lastName;
String avatar;
factory Data.fromJson(Map<String, dynamic> json) => _$DataFromJson(json);
Map<String, dynamic> toJson() => _$DataToJson(this);
}
this is the github link https://github.com/sbis04/dio_networking
Using Model to format data, is depend on developer strategy.For example here they want to categorize the user data in to different for. They have User which have a property of data that provide with other model class which is some user informations. They have other model class called UserInfo which hold other user information than Data class.

Flutter Freezed/json_serializable - runtimeType is missing from generated json

For some reason the runtimeType is missing in the generated json of this Freezed class. It only happens sometimes. See image below:
This causes the switch case in the image to fall through to throw FallThroughError();, since runtimeType doesn't exist.
Here is the class:
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:vepo/src/application/entities/option/option.dart';
import '../vegan_item.dart';
part 'basic_vegan_item.freezed.dart';
part 'basic_vegan_item.g.dart';
#freezed
class BasicVeganItem extends VeganItem with _$BasicVeganItem {
const factory BasicVeganItem(
{int? id,
String? name,
String? companyName,
String? imageBucketName,
String? description,
String? image,
List<Option>? tags,
#Default(0) int isNotVeganCount,
#Default(0) int isVeganCount,
int? rating,
#Default(0) int ratingsCount,
#Default(1) int currentRevisionId}) = _BasicVeganItem;
const factory BasicVeganItem.groceryItem(
{int? id,
String? name,
String? companyName,
#Default('vp-grocery-items') String? imageBucketName,
String? description,
String? image,
List<Option>? tags,
#Default(0) int isNotVeganCount,
#Default(0) int isVeganCount,
int? rating,
#Default(0) int ratingsCount,
#Default(1) int currentRevisionId}) = GroceryItem;
const factory BasicVeganItem.menuItem(
{int? id,
String? name,
String? companyName,
#Default('vp-menu-items') String? imageBucketName,
String? description,
String? image,
List<Option>? tags,
#Default(0) int isNotVeganCount,
#Default(0) int isVeganCount,
int? rating,
#Default(0) int ratingsCount,
#Default(1) int currentRevisionId}) = MenuItem;
const BasicVeganItem._();
factory BasicVeganItem.fromJson(Map<String, dynamic> json) =>
_$BasicVeganItemFromJson(json);
}

Flutter: json_serializable ignore nullable fields instead of throwing an error

Suppose there are two models User and City
#JsonSerializable()
class User {
int id;
String name;
City? city;
List<Map<String, City>>? listMapCity;
}
#JsonSerializable()
class City {
int id;
String name;
}
Now suppose during API call, we've got a user model but in the city object model, we only get id not name. Something like this
{
"id": 5,
"name": "Matthew",
"city": {
"id": 12
}
}
But due to the default nature of json_serializable and json_annotation.
This JSON is not mapped to the User model, during mapping, it throws the exception.
type Null is not a subtype of type String. (because here name key is missing in city object)
But as we already declared in the User object that City is optional, I wanted that it should parse the User JSON with city and listMapCity to be null.
Any help or solution would be really appreciated, Thank you
You need to set the includeIfNull flag to false to have the autogenerated code handle nulls correctly.
#JsonSerializable(includeIfNull: false)
The property should be declared with a ? as per your example.
You need to have a default constructor on your JsonSerializable User class. Then, if name should be nullable, declare it with a nullable String? name;
Here's the updated User class.
import 'package:json_annotation/json_annotation.dart';
part 'user.g.dart';
#JsonSerializable()
class User {
int id;
String name;
City? city;
List<Map<String, City>>? listMapCity;
User({required this.id, required this.name, this.city, this.listMapCity});
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}
#JsonSerializable()
class City {
int id;
String name;
City({required this.id, required this.name});
}

Flutter json_serializable Build failing

I am using json_serializable, json_annotation, and build to generate serialization/deserialization functionality for my models. When I run the build though, I get this error.
Error running JsonSerializableGenerator
Cannot populate the required constructor argument: created.
package:explorer/models/Account/account.dart:46:3
The line it is referring to is my model constructor which is this.
Account(String id, String firstName, String lastName, String email,
DateTime dob, DateTime created, DateTime updated,
{String accessTkn, String refreshTkn}) {}
Why am I getting this error?
As requested, here is my model class.
import "package:json_annotation/json_annotation.dart";
part "account.g.dart";
#JsonSerializable(nullable: true)
class Account {
#JsonKey(name: "id")
String _id;
#JsonKey(name: "first_name")
String _firstName;
#JsonKey(name: "last_name")
String _lastName;
#JsonKey(name: "email")
String _email;
#JsonKey(
name: "dob", fromJson: _isoStringToDateTime, toJson: _dateTimeToIsoString)
DateTime _dob;
#JsonKey(
name: "created",
fromJson: _isoStringToDateTime,
toJson: _dateTimeToIsoString)
DateTime _created;
#JsonKey(
name: "updated",
fromJson: _isoStringToDateTime,
toJson: _dateTimeToIsoString)
DateTime _updated;
#JsonKey(name: "access_token")
String _accessToken;
#JsonKey(name: "refresh_token")
String _refreshToken;
Account(String id, String firstName, String lastName, String email,
DateTime dob, DateTime created, DateTime updated,
{String accessTkn, String refreshTkn}) {
this._id = id;
this._firstName = firstName;
this._lastName = lastName;
this._email = email;
this._dob = dob;
this._created = created;
this._updated = updated;
this._accessToken = accessToken;
this._refreshToken = refreshTkn;
}
factory Account.fromJson(Map<String, dynamic> json) {
_$AccountFromJson(json);
}
// converts a DateTime to a ISO string
static String _dateTimeToIsoString(DateTime date) {
return date.toIso8601String();
}
// convert back to date time
static DateTime _isoStringToDateTime(String iso) {
return DateTime.parse(iso);
}
/// get the account id
String get id {
return this._id;
}
/// get the account first name
String get firstName {
return this._firstName;
}
/// get the account last name
String get lastName {
return this._lastName;
}
/// get the account email.
String get email {
return this._email;
}
/// get the account owner's date of birth
DateTime get dob {
return this._dob;
}
/// Get the date the account was created.
DateTime get createdAt {
return this._created;
}
/// get teh date the account was last updated.
DateTime get updatedAt {
return this._updated;
}
// get the account access token.
String get accessToken {
return this._accessToken;
}
// get the account refresh token.
String get refreshToken {
return this._refreshToken;
}
/// clones the account instance
Account clone() {
return Account(this.id, this.firstName, this.lastName, this.email, this.dob,
this.createdAt, this.updatedAt,
accessTkn: this.accessToken, refreshTkn: this.refreshToken);
}
Map<String, dynamic> toJson() {
_$AccountToJson(this);
}
}
You are getting the error because you didn't initialize passed parameters, you have an empty constructor.
You have to initialize every parameter you have in your class, or allow them to be nullable with JsonSerializable(nullable: true) or JsonKey(nullable: true)
Please share all code in your class if that solution wouldn't work for you
EDIT:
The library works with reflection, I understand where was an error.
Attributes should be named the same as your parameters.
Your getters should be named the same as your parameters
Change your code with next fixes:
Account(String id, String firstName, String lastName, String email,
DateTime dob, DateTime created, DateTime updated,
String accessToken, String refreshToken) {
this._id = id;
this._firstName = firstName;
this._lastName = lastName;
this._email = email;
this._dob = dob;
this._created = created;
this._updated = updated;
this._accessToken = accessToken;
this._refreshToken = refreshToken;
}
/// Get the date the account was created.
DateTime get created {
return this._created;
}
/// get teh date the account was last updated.
DateTime get updated {
return this._updated;
}
For future reference, I would like to explain the problem above with an example and suggest a general solution for it:
json_serializable + json_annotation use the constructor parameter names as the json field keys. So there is a distinct difference between the two examples below:
#JsonSerializable()
class User {
#JsonKey(name: "first_name") final String firstName;
// In this case, the json key becomes 'first_name',
// extracted from the explicitly referenced field annotation.
const User(this.firstName);
}
#JsonSerializable()
class User {
#JsonKey(name: "first_name") String _firstName;
String get firstName => _firstName?.trim();
// In this case, the json key becomes 'firstName',
// extracted from the constructor parameter name.
// For reflection, the field and its annotation are not involved.
User(String firstName) {
this._firstName = firstName;
}
}
The reason we want to hide a field is twofold; We don't want others to be able to update its value, and we want to provide a 'corrected' (in this case, trimmed) value rather than the unvalidated value retrieved from an external source. Since we are unable to neatly hide the unvalidated value, I'd suggest we do expose it but explicitly mention its shortcomings, like so:
#JsonSerializable()
class User {
// The field is final, so its value cannot be altered as if private.
// It is exposed (sadly), but clearly mentions potential issues.
#JsonKey(name: "first_name") final String firstNameUntrimmed;
// This is the 'corrected' version available with a more pleasant field name.
String get firstName => firstNameUntrimmed?.trim();
const User(this.firstNameUntrimmed);
}