Firebase Cloud Function创建文档报错:返回不是有效JSON对象
问题详情
在Flutter应用中使用Firestore数据库,需求是每个用户在UserFavourites集合下拥有一个以自身UID命名的专属文档。我编写了一个HTTPS可调用云函数,逻辑为检查目标文档是否存在,不存在则创建。但调用函数时触发错误:Error: internal Response is not valid JSON object,且测试用户的文档并未成功创建。
云函数代码
exports.createUserFavouritesDocument = functions .region("europe-west2") .https.onCall(async (data, context) => { const uid = data.uid; const favouritesRef = admin .firestore().collection("UserFavourites").doc(uid); return favouritesRef.get().then((doc) => { if (doc.exists) { return { success: true }; } else { return favouritesRef.set({ Stores: [] }) .then(() => { return { success: true }; }) .catch((error) => { // throw new functions // .https // .HttpsError("internal", "Error creating document.", error); return { error: "Error creating doc" }; }); } }).catch((error) => { if (error.code === "not-found") { return favouritesRef.set({ Stores: [] }) .then(() => { return { success: true }; }) .catch((error) => { // throw new functions // .https // .HttpsError("internal", "Error creating document.", error); return { error: "Error creating document" }; }); } else { // throw new functions // .https // .HttpsError("internal", "Error checking for document.", error); return { error: "Error creating document" }; } }); });
Flutter调用代码
void _checkdoc() async { try { final result = await createUserFavouritesDocument.call(<String, dynamic>{ 'uid': FirebaseAuth.instance.currentUser!.uid, }); print(result.data); } on FirebaseFunctionsException catch (e) { print("error"); print('Error: ${e.code} ${e.message}'); } catch (e) { print('Error: $e'); } }
解决方案
问题根源
- 错误处理不规范:Callable函数要求错误必须抛出
functions.https.HttpsError类型,你注释掉了正确的错误抛出逻辑,返回普通对象会导致客户端解析JSON失败,触发Response is not valid JSON object错误。 - 异步逻辑混乱:混合使用
async/await和.then/.catch,容易导致返回值不符合预期。 - UID获取不安全:从
data.uid获取用户ID存在被篡改风险,应该从云函数的context.auth.uid获取(前提是客户端已通过Firebase Auth认证)。
修正后的云函数代码
exports.createUserFavouritesDocument = functions .region("europe-west2") .https.onCall(async (data, context) => { // 验证用户是否已认证 if (!context.auth) { throw new functions.https.HttpsError( "unauthenticated", "用户未登录,无法执行此操作" ); } const uid = context.auth.uid; const favouritesRef = admin.firestore().collection("UserFavourites").doc(uid); try { const doc = await favouritesRef.get(); if (doc.exists) { return { success: true, message: "文档已存在" }; } else { await favouritesRef.set({ Stores: [] }); return { success: true, message: "文档创建成功" }; } } catch (error) { throw new functions.https.HttpsError( "internal", "操作失败", error.message ); } });
优化后的Flutter调用代码
void _checkUserFavouritesDoc() async { try { final user = FirebaseAuth.instance.currentUser; if (user == null) { print("用户未登录"); return; } final result = await createUserFavouritesDocument.call({}); print(result.data); } on FirebaseFunctionsException catch (e) { print('云函数错误: ${e.code} - ${e.message}'); } catch (e) { print('未知错误: $e'); } }
额外检查
- 确保云函数服务账号拥有Firestore的读写权限,可在Firebase控制台的「规则」中配置
UserFavourites集合的权限:
match /UserFavourites/{userId} { allow read, write: if request.auth != null && request.auth.uid == userId; }
- 确认云函数已正确部署到
europe-west2区域,Flutter端的Callable函数也需指定相同区域。
内容的提问来源于stack exchange,提问作者ReDue
相关产品推荐
相关产品推荐

