Firebase:将数据传递给 cloudfunction 导致:对象无法用 JSON 编码
Posted
技术标签:
【中文标题】Firebase:将数据传递给 cloudfunction 导致:对象无法用 JSON 编码【英文标题】:Firebase: passing data to cloudfunction results in: Object cannot be encoded in JSON 【发布时间】:2018-10-12 18:27:51 【问题描述】:我尝试调用云函数并传递一些数据。我的数据是Map<String, Object>
类型,里面又嵌套了一些Map<String, Object>
。当试图用这个调用我的函数时:
getHttpsCallable(function).call(data)...
我得到这个错误:
Cloud Function Exception:
java.lang.IllegalArgumentException: Object cannot be encoded in JSON: [Ljava.util.Map;@42896770
at com.google.firebase.functions.Serializer.encode(Serializer.java:136)
at com.google.firebase.functions.Serializer.encode(Serializer.java:77)
at com.google.firebase.functions.FirebaseFunctions.call(FirebaseFunctions.java:255)
at com.google.firebase.functions.FirebaseFunctions.access$100(FirebaseFunctions.java:34)
at com.google.firebase.functions.FirebaseFunctions$2.then(FirebaseFunctions.java:233)
at com.google.firebase.functions.FirebaseFunctions$2.then(FirebaseFunctions.java:225)
at com.google.android.gms.tasks.zzd.run(Unknown Source)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5653)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
at dalvik.system.NativeStart.main(Native Method)
打印我的数据对象时,它看起来像这样:
items=[Ljava.util.Map;@42896770, element1=OzNGHzHeq6av03hRmMJ6, time=Sun May 05 04:40:00 MEZ 3918
我尝试了以下方法: 我尝试在我的数据对象中打包一个数组而不是一个 Map。 => 没用。
我自己尝试将我的数据转换成json并发送,这也没有用。
我做了以下操作:
Gson gson = new Gson();
String dataJSON = gson.toJson(data);
最终生成了格式良好的 JSON:
"items":["count":1,"itemId":"94To3bKnxoWzayLdy55I","count":3,"itemId":"fkNtIUxbfg5GhLJy2Dma","count":1,"itemId":"sDYTp7cpQTRfWuI6CSaK","count":1,"itemId":"qGGl5U0qihHnMzhBMjyb","options":["2.0","1.0","1.1","0.0"],"count":1,"itemId":"qGGl5U0qihHnMzhBMjyb","options":["2.0","1.0","1.1","0.1"],"count":1,"itemId":"qGGl5U0qihHnMzhBMjyb","options":["2.0","1.0","1.1","0.2"],"count":1,"itemId":"qGGl5U0qihHnMzhBMjyb","options":["2.3","1.0","1.1","0.1"]],"storeId":"OzNGHzHeq6av03hRmMJ6","pickupTime":"May 5, 3918 4:40:00 AM"
但我也尝试使用硬编码的 JSON 调用我的函数,但它也不起作用。
我不知道我做错了什么。有人知道吗?
【问题讨论】:
也许使用 Gson 库 mkyong.com/java/… 或 github.com/google/gson @RenaudTarnec 我做到了。我在我的方法中使用它来发送预构建 json。items=[Ljava.util.Map;@42896770,...
不看 JSON...
是的。当只是尝试我在最初的问题文本中所说的内容时,它看起来像这样。我刚刚在我的问题中告诉我,我还尝试了一些其他的东西,包括用 gson 生成一个 json。
你能分享你用 Gson 写的代码来将你的 java 对象转换成 JSON 吗?
【参考方案1】:
问题是您实际上传递了array
的Map
对象。
由于 Frederik Byl 显示了 Functions SDK for Android 的源代码,它不接受数组类型。它接受Map
或List
Java Collection 对象。
因此,您必须将您的 [Ljava.util.Map;
类型更改为 List<Map>
。
另外,实际上 Firestore 使用 Protobuf 作为核心数据集。您可以在here 找到更多信息,他们如何使用 Protobuf 数据对 json 进行编码或解码。
【讨论】:
【参考方案2】:我认为您应该从数据对象中创建并传递一个 JSONObject。不是字符串或数据对象: 像这样:
Gson gson = new Gson();
String jsonString = gson.toJson(data);
JSONObject jsonObj = null;
try
jsonObj = new JSONObject(jsonString);
catch (JSONException e)
e.printStackTrace();
因为:
public Object encode(Object obj)
if (obj != null && obj != JSONObject.NULL)
JSONObject result;
if (obj instanceof Long)
result = new JSONObject();
try
result.put("@type", "type.googleapis.com/google.protobuf.Int64Value");
result.put("value", obj.toString());
return result;
catch (JSONException var9)
throw new RuntimeException("Error encoding Long.", var9);
else if (obj instanceof Number)
return obj;
else if (obj instanceof String)
return obj;
else if (obj instanceof Boolean)
return obj;
else if (obj instanceof JSONObject)
return obj;
else if (obj instanceof JSONArray)
return obj;
else
Object o;
String key;
Object value;
Iterator keys;
if (obj instanceof Map)
result = new JSONObject();
Map<?, ?> m = (Map)obj;
keys = m.keySet().iterator();
while(keys.hasNext())
o = keys.next();
if (!(o instanceof String))
throw new IllegalArgumentException("Object keys must be strings.");
key = (String)o;
value = this.encode(m.get(o));
try
result.put(key, value);
catch (JSONException var10)
throw new RuntimeException(var10);
return result;
else
JSONArray result;
if (obj instanceof List)
result = new JSONArray();
List<?> l = (List)obj;
keys = l.iterator();
while(keys.hasNext())
o = keys.next();
result.put(this.encode(o));
return result;
else
JSONObject wrapped;
if (obj instanceof JSONObject)
result = new JSONObject();
wrapped = (JSONObject)obj;
keys = wrapped.keys();
while(keys.hasNext())
String k = (String)keys.next();
if (!(k instanceof String))
throw new IllegalArgumentException("Object keys must be strings.");
key = k;
value = this.encode(wrapped.opt(k));
try
result.put(key, value);
catch (JSONException var11)
throw new RuntimeException(var11);
return result;
else if (!(obj instanceof JSONArray))
if (obj instanceof Date)
String utc = this.dateFormat.format((Date)obj);
wrapped = new JSONObject();
try
wrapped.put("@type", "type.googleapis.com/google.protobuf.Timestamp");
wrapped.put("value", utc);
return wrapped;
catch (JSONException var12)
throw new RuntimeException("Error encoding Date.", var12);
else
throw new IllegalArgumentException("Object cannot be encoded in JSON: " + obj);
else
result = new JSONArray();
JSONArray l = (JSONArray)obj;
for(int i = 0; i < l.length(); ++i)
o = l.opt(i);
result.put(this.encode(o));
return result;
【讨论】:
【参考方案3】:传递 org.json.JSONObject
而不是 com.google.gson.JsonObject
就可以了。
您无需在 firebase 函数上使用地图。
【讨论】:
以上是关于Firebase:将数据传递给 cloudfunction 导致:对象无法用 JSON 编码的主要内容,如果未能解决你的问题,请参考以下文章