0

I am sending an object from Google Apps Script through a webhook to Mongo Stitch (with a http service). The input object is {A=185, B=8, C=200} and once inserted into the DB it becomes {A="185", B="8", C="200"}. How do I avoid the numbers being converted to string when saved in the DB?

On Google Apps Script-side I have:

function sendToStitch(){
  var obj = {A=185, B=8, C=200};
  var options = {
      'method' : 'post',
      'payload' : obj
    };
  var insertID = UrlFetchApp.fetch('https://eu-west-1.aws.webhooks.mongodb-stitch.com/api/client/v2.0/app/timesheetstest-fgidp/service/sheets/incoming_webhook/import', options);
} 

On Stitch-side I have in a http service:

exports = async function(payload) {
   const mongodb = context.services.get("mongodb-atlas");
   const eventsdb = mongodb.db("time");
   const eventscoll = eventsdb.collection("sheets");
   const result = await eventscoll.insertOne(payload.query);
   var id = result.insertedId.toString();
   if(result) {
      return JSON.stringify(id,false,false);   
   }
   return { text: `Error saving` };
}

How can I make sure that the object values are inserted with a number type? (same as in the input object, I verified this Google Apps Script-side).

Any suggestions?

Thanks!

jlo
  • 2,157
  • 2
  • 17
  • 23

1 Answers1

1

How can I make sure that the object values are inserted with a number type? (same as in the input object, I verified this Google Apps Script-side).

According to the documentation of Google Apps Script UrlFetchApp. The payload can be a string, a byte array, a blob, or a JavaScript object. With the JavaScript object is interpreted as a map of form field names to values, where the values can be either strings or blobs.

I think this is the reason why the data is in string, because the object that is being sent is converted into:

{"A": "185", "B": "8", "C":"200"}

One of the ways to ensure the numeric stays numeric is to sent data in Extended JSON format. First, convert the JavaScript object to JSON string in Google Apps Script:

Option A)

function sendToStitch(){
  var obj = {A:285, B:28, C:300};
  var options = {
      'method' : 'post',
      'contentType': 'application/json',
      'payload' : JSON.stringify(obj)
    };
  var insertID = UrlFetchApp.fetch('https://eu-west-1.aws.webhooks.mongodb-stitch.com/api/client/v2.0/app/timesheetstest-fgidp/service/sheets/incoming_webhook/import', options);
} 

Option B)

function sendToStitch(){
  var obj = {"A": {"$numberLong": "185"}, 
             "B": {"$numberLong": "8" }, 
             "C": {"$numberLong": "200"}};
  var options = {
      'method' : 'post',
      'contentType': 'application/json',
      'payload' : JSON.stringify(obj)
    };
  var insertID = UrlFetchApp.fetch('https://someurl/incoming_webhook', options);
} 

In the MongoDB Stitch Functions you can then just parse the input using EJSON.parse(). For example:

exports = async function(payload) {
   let doc = EJSON.parse(payload.body.text());
   const coll = context.services.get("mongodb-atlas")
                          .db("time")
                          .collection("sheets");
   const result = await coll.insertOne(doc);
   if(result) {
      return result;
   }
   return { text: `Error saving` };
}
jlo
  • 2,157
  • 2
  • 17
  • 23
Wan B.
  • 18,367
  • 4
  • 54
  • 71
  • If I have 'contentType': 'application/json' in the options, what arrives to Stitch is a payload with payload.query={} (the rest of the payload is fine, it even reflects the right "Content-Length":["71"]). If I don't have the contentType line I get "query":{"{\"A\":{\"$numberLong\":185},\"B\":{\"$numberLong\":8},\"C\":{\"$numberLong\":200}}":""}, but got no way to parse that (tried JSON.parse(payload.query) & EJSON.parse(payload.query) from Stitch-side to no avail). Any ideas? UrlFetchApp works fine, tested it with a different URL from webhook.site. The problem seems to be Stitch side – jlo Jan 22 '20 at 12:32
  • 1
    @jlo, when you set to `application/json` did you also `JSON.stringify()` the payload ? Could you also try in Stitch to see what the `payload.body` is ? You can try: `const body = payload.body? payload.body.text() : payload body;` then do `const data = EJSON.parse(body);` The posted line that you get is quite interesting, because the JSON key is the value that you're after. – Wan B. Jan 22 '20 at 22:25
  • Thank you very much, that did it. So the key of the whole thing is that when sending an 'application/json' payload, it's inside payload.body not payload.query. Also $numberLong is not needed for this to work (see option a) – jlo Jan 23 '20 at 10:06