web-dev-qa-db-ja.com

AndroidでJsonデータを解析する方法

プッシュメッセージにFCMを使用し、すべての着信プッシュ通知をonMessageReceivedで処理しています。今問題は、この関数の内部にあるネストされたjsonの解析にありますremoteMessage.getData()

デバイスでプッシュ通知として次のブロックが来ています。データペイロードの内容はここで変化する可能性があります。後でディーラーになることもできますproductInfo

_{
  "to": "/topics/DATA",
  "priority": "high",
  "data": {
    "type": 6,
    "dealerInfo": {
      "dealerId": "358",
      "operationCode": 2
    }
  }
}
_

これは私がそれをどのように解析しているか

_ if(remoteMessage.getData()!=null){

        JSONObject object = null;
        try {
            object = new JSONObject(remoteMessage.getData());       

        } catch (JSONException e) {
            e.printStackTrace();
        }


    }
_

remoteMessage.getData()が_Map<String,String>_を返すので、今は黒スラッシュでデータを取得しています。

_{
  "wasTapped": false,
  "dealerInfo": "{\"dealerId\":\"358\",\"operationCode\":2}",
  "type": "6"
}
_

そして、私がobject = new JSONObject(remoteMessage.getData().toString());と書いた場合、次の通知で失敗しました

_{
  "to": "regid",
  "priority": "high",
  "notification" : {
      "body": "Message Body",
      "title" : "Call Status",
      "click_action":"FCM_PLUGIN_ACTIVITY"
   },
  "data": {
    "type": 1,
     "callNumber":"ICI17012702",
     "callTempId":"0",
      "body": "Message Body",
      "title" : "Call Status"
  }
}
_

エラー私は得ます

_> org.json.JSONException: Unterminated object at character 15 of
> {body=Message Body, type=1, title=Call Status, callNumber=ICI17012702,
> callTempId=0}
_
12
Hunt

このコードを試してください:

public void onMessageReceived(RemoteMessage remoteMessage)
    {
        Log.e("DATA",remoteMessage.getData().toString());
        try
        {
            Map<String, String> params = remoteMessage.getData();
            JSONObject object = new JSONObject(params);
            Log.e("JSON OBJECT", object.toString());
            String callNumber = object.getString("callNumber");
            //rest of the code
      }
   }

また、JSONが有効であることを確認してください This

11
rafsanahmad007

GCMからFCMに移行するときにこの問題に直面しました。

以下は私のユースケース(およびOPペイロード)で機能しているため、おそらく他のユーザーでも機能します。

JsonObject jsonObject = new JsonObject(); // com.google.gson.JsonObject
JsonParser jsonParser = new JsonParser(); // com.google.gson.JsonParser
Map<String, String> map = remoteMessage.getData();
String val;

for (String key : map.keySet()) {
    val = map.get(key);
    try {
        jsonObject.add(key, jsonParser.parse(val));
    } catch (Exception e) {
        jsonObject.addProperty(key, val);
    }
}

// Now you can traverse jsonObject, or use to populate a custom object:
// MyObj o = new Gson().fromJson(jsonObject, MyObj.class)
5
gonga

に変わった

JSONObject json = new JSONObject(remoteMessage.getData());

から

JSONObject json = new JSONObject(remoteMessage.getData().toString());

うまくいきます。

1
priyanka

dealerInfoはオブジェクトではなく文字列として解析されるため、文字列を使用して新しいJSONObjectを作成します

JSONObject dealerInfo = new JSONObject(object.getString("dealerInfo"));
String dealerId = dealerInfo.getString("dealerId");
String operationCode = dealerInfo.getString("operationCode");
0
kehers

(moshiを使用して)GSONを追加して機能させたくなかったので、KotlinメソッドでremoteMessageのマップからjson文字列を作成し、1つの例でこれをテストしたので、使用する前にこの実装をテストすることを忘れないでください。

override fun onMessageReceived(remoteMessage: RemoteMessage?) {
        super.onMessageReceived(remoteMessage)

        var jsonString = "{"

        remoteMessage?.data?.let {
            val iterator = it.iterator()

            while (iterator.hasNext()) {
                val mapEntry = iterator.next()
                jsonString += "\"${mapEntry.key}\": "
                val value = mapEntry.value.replace("\\", "")
                if (isValueWithoutQuotes(value)) {
                    jsonString += value
                } else {
                    jsonString += "\"$value\""
                }

                if (iterator.hasNext()) {
                    jsonString += ", "
                }
            }
        }

        jsonString += "}"


        println(jsonString)
    }

    private fun isValueWithoutQuotes(value: String):Boolean{
       return (value == "true" || value == "false" || value.startsWith("[") || value.startsWith("{") || value == "null" || value.toIntOrNull() != null )
    }

編集:

さらに良い方法は、次のようなFCMデータを作成することです。

notificationType: "here is ur notification type"
notificationData: {
//here goes ur data
}

これにより、マップから両方の値を取得できます。

remoteMessage?.data?.let {
    it["notificationData"]?.let {
         jsonString = it.replace("\\", "")
    }
}

遊び回らずにjsonをクリアしました。そして、notificationTypeを使用して、jsonを必要なオブジェクトに変換できます(いくつかの通知データ型が時々渡される可能性があるため)

0
Janusz Hain
 @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Log.d(TAG, "From: " + remoteMessage.getFrom());
        if (remoteMessage.getData().size() > 0) {
            Log.d(TAG, "Message data payload: " + remoteMessage.getData());

//            if (/* Check if data needs to be processed by long running job */ true) {
//                // For long-running tasks (10 seconds or more) use WorkManager.
//                scheduleJob();
//            } else {
//                // Handle message within 10 seconds
//                handleNow();
//            }

        }

        // Check if message contains a notification payload.
        if (remoteMessage.getNotification() != null) {
            Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
            sendNotification(remoteMessage.getNotification().getBody());
        }

    }
0