冻结的 Json 序列化程序 - Firestore 通信

Posted

技术标签:

【中文标题】冻结的 Json 序列化程序 - Firestore 通信【英文标题】:Json serializer with freezed - firestore comunication 【发布时间】:2021-07-26 14:12:07 【问题描述】:

我正在努力在我的项目中实现购物车功能,我正在尝试传递序列化的 JSON(使用冻结的包生成),但 CartItem 的列表有问题。 Error: Invalid argument (dartObject): Could not convert: Instance of '_$36_CartItem'

我的购物车模型:

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);

产品:

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);

购物车项目:

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);

向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'));
  

在 .g.dart 中生成 toJson(所有生成的文件都具有相同的 toJson 模式):

Map<String, dynamic> _$_$_UserToJson(_$_User instance) => <String, dynamic>
      'id': instance.id,
      'email': instance.email,
      'cart': instance.cart,
    ;

我认为问题在于CartItem 在我看来User.toJson() 应该调用对象中的所有 toJson 方法,但我是第一次实现它,所以我真的不知道。

我是否应该在 User 中编写自己的 toJson,然后调用 build runner 和 freezed 会重新生成新的 toJson?

【问题讨论】:

【参考方案1】:

您必须使用装饰器 @JsonKey(fromJson: User.cartItemFromJson, toJson: User.cartItemToJson) 作为购物车属性,并在您的 User 类中创建这两个静态方法:

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();

或者您可以创建一个实现 JsonConverter 的类并将该类用作装饰器,所有信息都在冻结的文档中:https://pub.dev/packages/freezed#fromjsontojson

【讨论】:

CartItem.toJson() 应该是什么样的?因为目前,我有这个错误。我将其更改为 item!.toJson 但现在错误只是产品转换器问题的一个实例。所以我也应该在 CartItem 里面写点东西对吧?

以上是关于冻结的 Json 序列化程序 - Firestore 通信的主要内容,如果未能解决你的问题,请参考以下文章

为啥即使我使用 Alamofire 发出请求,我的应用程序仍然冻结?

解析 JSON 冻结 tableView SWIFT

在 Project Navigator 中单击 JSON 文件时 Xcode 冻结(并崩溃)

v9升级后Angular应用程序冻结/无限加载而没有错误

当我尝试 JsonConvert.DeserializeObject <T> 时,我的 xamarin 应用程序冻结

HTML 5 Progress 元素冻结在活动中