Firebase: передача данных в облачную функцию приводит к следующему: объект не может быть закодирован в JSON

Я пытаюсь вызвать облачную функцию и передать некоторые данные. Мои данные относятся к типу 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}

Я пробовал следующее: Я попытался упаковать массив вместо карты внутри моего объекта данных. => Не сработало.

Я сам пытался преобразовать свои данные в 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

Renaud Tarnec 02.05.2018 17:23

@RenaudTarnec Я сделал. Я использовал его в своем подходе для отправки prebuild json.

progNewbie 02.05.2018 17:25
{items=[Ljava.util.Map;@42896770,... не смотрит JSON ...
Renaud Tarnec 02.05.2018 17:26

да. Это выглядит так, если просто попробовать то, о чем я говорю в своем первоначальном тексте вопроса. Я только что сказал в своем вопросе, что пробовал и другие вещи, в том числе создание json с помощью gson.

progNewbie 02.05.2018 17:34

Можете ли вы поделиться кодом, который вы написали, с Gson для преобразования вашего java-объекта в JSON?

Renaud Tarnec 02.05.2018 17:35

@RenaudTarnec: Пожалуйста, посмотрите мою правку

progNewbie 02.05.2018 17:40

Позвольте нам продолжить обсуждение в чате.

Renaud Tarnec 02.05.2018 17:44
5
7
3 065
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Я думаю, вам следует создать и передать 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;
                    }
                }
            }
Ответ принят как подходящий

Проблема в том, что вы фактически передаете array объектов Map.

Поскольку Фредерик Бил показывает исходный код Functions SDK для Android, он не принимает тип массива. Он принимает объект Java Collection Map или List.

Поэтому вы должны изменить свой [Ljava.util.Map; на тип List<Map>.

Кроме того, на самом деле Firestore использует Протобуф для основного набора данных. Вы можете найти дополнительную информацию о том, как они кодируют или декодируют json с данными Protobuf, на здесь.

Передача org.json.JSONObject вместо com.google.gson.JsonObject работает нормально.

Вам не нужно использовать Карты для функций firebase.

Другие вопросы по теме