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

Android以Map形式向Cloud Function发送JSON数据报错求助

解决Android调用Cloud Function时的JSON编码错误

问题现象

通过Postman向Cloud Function发送指定JSON数据可正常运行,但Android端以Map形式构造并发送相同结构数据时,出现错误:

Object cannot be encoded in JSON: User(phone=55512345)

相关代码示例

Postman请求数据

{
    "data": {
        "users": [
            {
                "phone": "55512345"
            },
            {
                "phone": "972525276676"
            },
            {
                "phone": "55512347"
            }
        ]
    }
}

Android代码

private fun addMessage(): Task<String>? {
    val usr1 = User("55512345")
    val usr2 = User("972525276676")
    val usr3 = User("55512347")
    val userList = listOf(usr1,usr2,usr3)

    val data: MutableMap<String, Any> = HashMap()
    data["users"] = userList

    functions.getHttpsCallable("getUsers")
        .call(data)
        .addOnFailureListener {
            Log.d("DTAG", it.toString())
        }
        .addOnSuccessListener {
            Log.d("DTAG","Ok: ${it.data.toString()}")
        }
    return null
}

User数据类

data class User(var phone:String)

Cloud Function代码

exports.getUsers = functions.https.onRequest(async (request, response) => {
    const data = request.body.data;
    if (data !== null && data.users !== null) {
    const users = data.users;
    const phonelist = users.map(user => user.phone.toString());
    const userlist = []

    const snapshot = await db.collection("users").get()
    snapshot.docs.forEach((userDoc) => {
        const phone = userDoc.get("phone")
        if(phone === null) return;
        const isContain = phonelist.reduce((acc, num) => acc || phone.includes(num), false)
        if(isContain) {
            userlist.push(userDoc.data())
        }
    })
    response.status(200).json({result: userlist})
    }     else{
       response.sendStatus(403)
    }
});

错误原因

  1. Firebase的getHttpsCallable().call()方法仅支持序列化JSON原生类型(基本类型、Map、List等),自定义User数据类无法直接被序列化。
  2. Android端用Callable函数调用方式,但Cloud Function是普通HTTP函数(onRequest),两者的请求格式处理逻辑不匹配。

解决方法

方法一:将User对象转换为Map结构

直接构造符合JSON格式的Map代替自定义User类,让Callable函数可以正常序列化:

private fun addMessage(): Task<String>? {
    // 用Map替代User类,构造符合要求的用户列表
    val userList = listOf(
        mapOf("phone" to "55512345"),
        mapOf("phone" to "972525276676"),
        mapOf("phone" to "55512347")
    )

    val data: MutableMap<String, Any> = HashMap()
    data["users"] = userList

    functions.getHttpsCallable("getUsers")
        .call(data)
        .addOnFailureListener {
            Log.d("DTAG", it.toString())
        }
        .addOnSuccessListener {
            Log.d("DTAG","Ok: ${it.data.toString()}")
        }
    return null
}

方法二:适配Cloud Function类型(改用Callable函数)

将Cloud Function从普通HTTP函数(onRequest)改为Callable函数(onCall),匹配Android端的调用方式:

exports.getUsers = functions.https.onCall(async (data, context) => {
    // Callable函数直接接收data参数,无需解析request.body
    if (!data?.users) {
        throw new functions.https.HttpsError('invalid-argument', '缺少用户数据');
    }

    const phonelist = data.users.map(user => user.phone.toString());
    const userlist = [];

    const snapshot = await db.collection("users").get();
    snapshot.docs.forEach((userDoc) => {
        const phone = userDoc.get("phone");
        if (!phone) return;
        const isContain = phonelist.some(num => phone.includes(num));
        if (isContain) {
            userlist.push(userDoc.data());
        }
    });

    return {result: userlist};
});

注:onCall函数会自动处理请求的序列化/反序列化,返回结果也会自动包装成Callable函数要求的格式,同时提供更规范的错误处理机制。

方法三:通过JSON库序列化User类(保留自定义类)

如果不想放弃User数据类,可以用Gson/Moshi等JSON库将User列表转换为可序列化的Map结构:

// 先添加Gson依赖到build.gradle
// implementation 'com.google.code.gson:gson:2.10.1'

private fun addMessage(): Task<String>? {
    val usr1 = User("55512345")
    val usr2 = User("972525276676")
    val usr3 = User("55512347")
    val userList = listOf(usr1,usr2,usr3)

    val gson = Gson()
    // 将User列表转成List<Map<String, String>>
    val userMapList = gson.fromJson(
        gson.toJson(userList),
        object : TypeToken<List<Map<String, String>>>() {}.type
    )

    val data: MutableMap<String, Any> = HashMap()
    data["users"] = userMapList

    functions.getHttpsCallable("getUsers")
        .call(data)
        .addOnFailureListener {
            Log.d("DTAG", it.toString())
        }
        .addOnSuccessListener {
            Log.d("DTAG","Ok: ${it.data.toString()}")
        }
    return null
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 06:46:08