You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firestore非同质文档使用withConverter报错问题咨询

Firestore非同质文档使用withConverter的问题

我在Firestore中有一个集合,其中的文档并非同质(不同文档的字段可能存在或缺失)。尝试多种方式为字段设置可空值,但对象执行fromJson转换时频繁抛出异常。

请问是否只有同质文档才能使用withConverter?

简化示例中,非管理员用户的文档不存在isAdmin字段:

class UserDocument {
  const UserDocument({
    required this.isAdmin,
    required this.location,
  });

  final bool? isAdmin;
  final String location;

  UserDocument.fromJson(Map<String, Object?> json)
      : this(
          isAdmin: json['is_admin'] as bool,
          location: json['location']! as String,
        );

  Map<String, Object?> toJson() => {
        'is_admin': isAdmin,
        'location': location,
      };
}

DocumentReference collectionDoc(String collectionName, String documentName) {
  return FirebaseFirestore.instance.collection(collectionName).doc(documentName);
}

Stream<DocumentSnapshot<UserDocument>> userStream() {
  final dataRef = collectionDoc("user", currentAuthUid).withConverter<UserDocument>(
      fromFirestore: (snapshots, _) => UserDocument.fromJson(snapshots.data()!), toFirestore: (user, _) => user.toJson());
  return dataRef.snapshots();
}

报错堆栈信息:

══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following TypeErrorImpl was thrown building StreamBuilder<DocumentSnapshot<UserDocument>>(dirty,
state: _StreamBuilderBaseState<DocumentSnapshot<UserDocument>,
AsyncSnapshot<DocumentSnapshot<UserDocument>>>#3621a):
Unexpected null value.

The relevant error-causing widget was:
  StreamBuilder<DocumentSnapshot<UserDocument>>

解答

不是只有同质文档才能使用withConverter,问题出在你的fromJson转换逻辑上:

  • 当文档中不存在is_admin字段时,json['is_admin']会返回null,但你用as bool强制转换非空的bool类型,null无法完成这个转换,直接触发了空值异常。
  • 虽然isAdmin被定义为bool?可空类型,但转换环节没正确处理null的情况。

直接修改fromJson里的isAdmin转换代码就能解决问题:

UserDocument.fromJson(Map<String, Object?> json)
    : this(
        isAdmin: json['is_admin'] as bool?, // 改为可空bool类型转换
        location: json['location']! as String,
      );

如果要更严谨,还可以先判断字段是否存在:

UserDocument.fromJson(Map<String, Object?> json)
    : this(
        isAdmin: json.containsKey('is_admin') ? json['is_admin'] as bool : null,
        location: json['location']! as String,
      );

另外提醒:如果location字段也可能缺失,那json['location']!会导致空指针,需要根据业务需求处理,比如给默认值或者把location也设为可空类型。

内容的提问来源于stack exchange,提问作者cmjordan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 21:30:14