I try to call a cloud function and pass some data. My data is of type Map<String, Object>
and inside it has again some nested Map<String, Object>
. When trying to call my function with this:
getHttpsCallable(function).call(data)...
I get this error:
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)
When printing my data object it looks like this:
{items=[Ljava.util.Map;@42896770, element1=OzNGHzHeq6av03hRmMJ6, time=Sun May 05 04:40:00 MEZ 3918}
I tried the following: I tried packing an array instead of a Map inside my data-object. => Did not work.
I tried to convert my data into a json myself and send it, this also didn't work.
I did the follwoing:
Gson gson = new Gson();
String dataJSON = gson.toJson(data);
which restulted in a nice formatted 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"}
But I also tried to call my function with a hardcoded JSON which did not work either.
I can't figure out what I am doing wrong. Does anyone know?
The problem is you are actually passing array
of Map
objects.
As Frederik Byl shows the source code of Functions SDK for Android, it won't accept array type. It accepts Map
or List
Java Collection object.
So you must change your [Ljava.util.Map;
to List<Map>
type.
Plus, actully Firestore uses Protobuf for core dataset. You can find more information at here how they encode or decode json with Protobuf data.
I think you should create and pass a JSONObject out of your data object. Not a string or the data object: like this:
Gson gson = new Gson();
String jsonString = gson.toJson(data);
JSONObject jsonObj = null;
try {
jsonObj = new JSONObject(jsonString);
} catch (JSONException e) {
e.printStackTrace();
}
because:
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;
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With