Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent FCM from converting nested json objects to string in Data Message notifications in react-native

I'm using firebase in my react-native project (with typescript), I set up all thing correctly and it works fine with data messages like below:

{
  "to": "fcm-token",

  "data": {
    "field1": "value1",
    "field2": "value1",
    "field3": "value1"
  }
}

in my App, I can access my data using data filed of RemoteMessage like below:

const data: MyDataType = remoteMessage.data;
const {/* destructed fields */} = data;

But when my server send nested Object to FCM server, it converts them to string and so I can not access them directly like above.

this is what my server send to FCM server:

{
  "to": "fcm-token",

  "data": {
    "field1": {
      "subfield1": "subvalue1",
      "subfield2": "subvalue2",
    },
    "field2": "value1",
    "field3": "value1"
  }
}

and this is what I get in my application:

{
  "to": "fcm-token",

  "data": {
    "field1": "{"subfield1": "subvalue1","subfield2": "subvalue2"}", <--- the problem is here, it must be a nested object not string
    "field2": "value1",
    "field3": "value1"
  }
}

I set Content-Type header to application/json in my server post requests, so I don't think there is any problem with my headers.

Am I doing something wrong? How can I prevent FCM from converting my nested objects?

like image 673
Saeed Zhiany Avatar asked May 29 '19 10:05

Saeed Zhiany


2 Answers

👋 react-native-firebase author here,

We don't internally convert anything to strings on our implementation, these come through to native as strings already, for example on Android this uses the RemoteMessage FCM class - where we call getData() which as you can see here returns strings only.

They way I've got around this myself if I want nested data is to have just a single data field where I provide all my data to as a single JSON string, then when receiving it I only need to JSON.parse a single field to get the structure back. E.g.

const data = {
  "field1": "value1",
  "field2": "value1",
  "field3": {
    "subfield1": "subvalue1",
  }
}

const payload = {
  "to": "fcm-token",
  "data": {
    "json": JSON.stringify(data),
  }
}
const data: MyDataType = remoteMessage.data;
const { field1, field2, field3 } = JSON.parse(data.json);

console.log(field3.subfield1);

Alternatively, you can flatten your data object before sending using something like this and then unflatten on the receiving end using something like this.

Hope this helps.

like image 96
Salakar Avatar answered Nov 10 '22 08:11

Salakar


If you look at the documentation for message type in the REST API, you'll see that data is declared as:

"data": {
  string: string,
  ...
},

So the data field can only hold string values, not more complex objects.

If you want to store more complex values, encode them as a string first and then decode them on the client, for example with JSON.stringify() and JSON.parse().

like image 29
Frank van Puffelen Avatar answered Nov 10 '22 09:11

Frank van Puffelen