【问题标题】:Error while serializing Built<Object> using built_value combined with FlutterFire使用 built_value 结合 FlutterFire 序列化 Built<Object> 时出错
【发布时间】:2021-08-16 21:49:21
【问题描述】:

我想在我的 Flutter 项目中将 built_valuecloud_firestore 结合起来。我相信这是有道理的,这就是在一个干净的世界中应该如何做到的? (见https://firebase.flutter.dev/docs/firestore/usage/#typing-collectionreference-and-documentreference)。

这是我目前为止的地方。

Place 模型:

// ../models/place.dart

import 'dart:convert';

import 'package:built_collection/built_collection.dart';
import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
import 'package:sitback/models/serializers.dart';

part 'place.g.dart';

abstract class Place implements Built<Place, PlaceBuilder> {
  // Fields

  String? get id;
  String get name;
  String get address;
  BuiltList<String> get methods;

  Place._();

  factory Place([void Function(PlaceBuilder) updates]) = _$Place;

  String toJson() {
    return json
        .encode(standardSerializers.serializeWith(Place.serializer, this));
  }

  // https://github.com/google/built_value.dart/issues/964#issuecomment-850419921
  static Place? fromJson(String jsonString) {
    return standardSerializers.deserializeWith(
        Place.serializer, json.decode(jsonString));
  }

  Map<String, Object?> toFirestore() {
    return serializers.serializeWith(Place.serializer, this);
  }

  // TODO: check if something can be improved
  // https://github.com/google/built_value.dart/issues/964#issuecomment-850419921
  static Place? fromFirestore(Map<String, dynamic> json) {
    return serializers.deserializeWith(Place.serializer, json);
  }

  static Serializer<Place> get serializer => _$placeSerializer;
}

在上面的代码中,我有两个问题:

  1. A value of type 'Object?' can't be returned from the method 'toFirestore' because it has a return type of 'Map&lt;String, Object?&gt;'

但是,这是在多个位置(SO 问题、github 问题)提出的解决方案,所以我不明白为什么会出现该错误。

  1. 在相同的参考教程/视频中,他们使用Place 而不是Place? 作为fromJson 的返回值,但随后出现以下错误:

A value of type 'Place?' can't be returned from the method 'fromJson' because it has a return type of 'Place'

这可能与最近的零安全变化有关吗?

以下是serializers(遵循文档/教程):

// ../models/serializers.dart

library serializers;

import 'package:built_collection/built_collection.dart';
import 'package:built_value/json_object.dart';
import 'package:built_value/serializer.dart';
import 'package:built_value/standard_json_plugin.dart';
import 'package:sitback/models/place.dart';

part 'serializers.g.dart';

@SerializersFor([
  Place,
])
final Serializers serializers = _$serializers;

final Serializers standardSerializers =
    (_$serializers.toBuilder()..addPlugin(StandardJsonPlugin())).build();

最后,这里是我想在使用通过built_value 包定义的Place“数据类”时使用 Firestore 集合的地方:

class IndexPage extends StatelessWidget {
  IndexPage({
    Key? key,
  }) : super(key: key);

  final placesRef = FirebaseFirestore.instance
      .collection('places')
      .withConverter<Place>(
        // TODO: ! at the end due to Place? vs Place in class definition
        // would require a try-catch or something else?
        fromFirestore: (snapshot, _) => Place.fromFirestore(snapshot.data()!)!,
        toFirestore: (place, _) => place.toFirestore(),
      );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: StreamBuilder<QuerySnapshot<Place>>(
          stream: placesRef.snapshots(),
          builder: (context, snapshot) {
            if (!snapshot.hasData) {
              return Center(
                child: CircularProgressIndicator(),
              );
            } else {
              return CustomScrollView(
                slivers: <Widget>[
                  SliverList(
                    delegate: SliverChildBuilderDelegate(
                      (context, index) {
                        final itemData = snapshot.data!.docs[index];
                        return PlaceCard(itemData: itemData);
                      },
                      childCount: snapshot.data!.docs.length,
                    ),
                  ),
                ],
              );
            }
          },
        ),
      ),
    );
  }
}

由于这条线,它目前无法正常工作: toFirestore: (place, _) =&gt; place.toFirestore(),。如果我从toFirestore() 返回{},那么它会编译并工作

但我怀疑 fromFirestore() 甚至都没有被调用:如果我将 assert(false); 放在函数中,什么都不会发生。除了一个例外,我会。

【问题讨论】:

    标签: flutter dart google-cloud-firestore built-value


    【解决方案1】:

    您不能对 Firestore 使用序列化程序。您需要从构建的值对象手动创建地图以上传它。一旦你想从 Firebase 获取,你需要从地图创建一个构建对象。最近没做过,但应该是这样的:

    static Place _fromFirestore(Map<dynamic, dynamic> placeMap) {
        final List<dynamic> methods = placeMap['methods'] ?? [];
        
        final place = Place((b) => b
          ..id = placeMap['id']
          ..name = placeMap['name']
          ..address = placeMap['address']
          ..methods.addAll(List<String>.from(methods.cast<String>()));
          
        return place;
      }
    

    【讨论】:

      猜你喜欢
      • 2016-06-11
      • 2014-04-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-25
      相关资源
      最近更新 更多