title: HTTP POST Request with JSON payload in Google Apps Script
body: <p>I'm having trouble getting Google App Script's <a href="https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app" rel="nofollow noreferrer">UrlFetchApp</a> class to correctly format a JSON payload in a HTTP request.</p>
  
  <p>Here's how I'm formatting the payload:</p>
  
  <pre><code>var data = {
    'RequestData': {
      'ItemNumber': '1',
      'StockItemId': '2',
      'ImageUrl': 'www.example.com'
    }
  };
  
  var payload = JSON.stringify(data);
  </code></pre>
  
  <p>Surely enough, <code>Logger.log(payload)</code> returns:</p>
  
  <pre><code>{"RequestData":{"ItemNumber":"1","StockItemId":"2","ImageUrl":"www.example.com"}}
  </code></pre>
  
  <p>However, when I integrate this with the actual request:</p>
  
  <pre><code>var url = 'https://example.com/api/method';
  
  var options = {
    'method': 'post',
    'contentType':'application/json',
    'payload': payload,
    'muteHttpExceptions': true
  };
  </code></pre>
  
  <p>and examine <code>Logger.log(UrlFetchApp.getRequest(url, options).toSource())</code>, I get this:</p>
  
  <pre><code>({method:"post",
  payload:"{\"RequestData\":{\"ItemNumber\":\"1\",\"StockItemId\":\"2\",\"ImageUrl\":\"www.example.com\"}}",
  followRedirects:true,
  validateHttpsCertificates:true,
  useIntranet:false, contentType:"application/json",
  url:"https://example.com/api/method"})
  </code></pre>
  
  <p>i.e. all the quotes are escaped, as if JSON.stringify is being called twice on the payload.</p>
  
  <p>I thought GAS might be calling an equivalent of JSON.stringify on the payload behind the scenes because contentType is specified as "application/json" but if I pass the data raw without stringifying it, I get:</p>
  
  <pre><code>({method:"post",
  payload:"RequestData=%7BItemNumber%3D1,+StockItemId%3D2,+ImageUrl%3Dwww.example.com%7D",
  followRedirects:true,
  validateHttpsCertificates:true,
  useIntranet:false, contentType:"application/json",
  url:"https://example.com/api/method"})
  </code></pre>
  
  <p>which is weird and (I'm pretty sure) an invalid JSON string. Either way, the request fails (400 Bad Request) and I'm pretty sure it's because I can't get the JSON across properly.</p>
  
  <p>All the docs and examples I can find seem to suggest that <code>JSON.stringify(payload)</code> is the way to go but I'm clearly having issues...</p>
  
  <p>Have also had the thought that this might have something to do with the implementation of the <code>.toSource()</code> method and that my problem might lie elsewhere but I have no way of knowing / otherwise being able to check the request body I'm sending.</p>
  
  <p>Any insight would be much appreciated!</p>