Reputation: 509
I'm struggling to implement the cart feature inside my project, I'm trying to pass the serialized JSON (generated with freezed package) but I've got a problem with the List of CartItem
. Error: Invalid argument (dartObject): Could not convert: Instance of '_$36_CartItem'
My models for cart:
part 'user.freezed.dart';
part 'user.g.dart';
@freezed
class User with _$User {
factory User({
required final String id,
required final String email,
required List<CartItem> cart,
}) = _User;
const User._();
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
}
Product:
part 'product.freezed.dart';
part 'product.g.dart';
@freezed
class Product with _$Product {
factory Product({
required final String id,
required final String name,
required final double price,
required final bool isBestseller,
required final String description,
required final String imageUrl,
}) = _Product;
const Product._();
factory Product.fromJson(Map<String, dynamic> json) =>
_$ProductFromJson(json);
}
CartItem:
part 'cart_item.freezed.dart';
part 'cart_item.g.dart';
@freezed
class CartItem with _$CartItem {
factory CartItem({
required final Product product,
required int quantity,
}) = _CartItem;
const CartItem._();
factory CartItem.fromJson(Map<String, dynamic> json) =>
_$CartItemFromJson(json);
}
Method for passing data to firestore:
Future<void> firebaseCreateUser(firebase_auth.User user) async {
CollectionReference users = FirebaseFirestore.instance.collection('users');
List<CartItem> test = [
CartItem(product: MockData.mockProducts.elementAt(0), quantity: 2),
CartItem(product: MockData.mockProducts.elementAt(1), quantity: 2)
];
return users
.doc(user.uid)
.set(User(cart: test, email: user.email!, id: user.uid).toJson())
.catchError((e) => print('Failed to add user: $e'));
}
Generated toJson
inside .g.dart (all generated files has same pattern for toJson):
Map<String, dynamic> _$_$_UserToJson(_$_User instance) => <String, dynamic>{
'id': instance.id,
'email': instance.email,
'cart': instance.cart,
};
I think that the problem lies in the CartItem
in my opinion User.toJson()
should call all toJson methods down in the object but I'm implementing it the first time so I don't really know.
Should I write my own toJson in User and then call build runner and freezed will regenerate new toJson?
Upvotes: 3
Views: 1797
Reputation: 86
cart items objects need to be converted to Maps.
in order to serialize nested objects, you have to change explicit_to_json
to true
in your build.yaml
file (create one if it does not exist)
https://github.com/google/json_serializable.dart/tree/master/json_serializable#build-configuration
Upvotes: 1
Reputation: 839
You will have to use the decorator @JsonKey(fromJson: User.cartItemFromJson, toJson: User.cartItemToJson) for the cart property and create those 2 static methods inside your User class:
part 'user.freezed.dart';
part 'user.g.dart';
@freezed
class User with _$User {
factory User({
required final String id,
required final String email,
@JsonKey(fromJson: User.cartItemFromJson, toJson: User.cartItemToJson)
required List<CartItem> cart,
}) = _User;
const User._();
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
static cartItemFromJson(List<dynamic?> listOfItem) => listOfItem.isEmpty ? []
: listOfItem.map((item) => CartItem.fromJson(item)).toList();
static cartItemToJson(List<CartItem?> items) => items.isEmpty ? []
: items.map((item) => CartItem.toJson()).toList();
}
Or you can create a class which implements JsonConverter and use this class as a decorator, all the info is in the freezed documentation: https://pub.dev/packages/freezed#fromjsontojson
Upvotes: 6