【问题标题】:How to fix Invalid JSON payload error from the Google Ads API如何修复来自 Google Ads API 的无效 JSON 负载错误
【发布时间】:2020-08-27 09:56:35
【问题描述】:

我正在尝试将 Google Ads API 中的报告提取到 Google 表格中,但我无法让 API 将我的查询识别为查询

这是我得到的代码和错误:

    function basicReport() {
  var query = {
    "query" : "SELECT campaign.name, campaign.status FROM campaign ORDER BY campaign.id"
  };
  
  var body = JSON.stringify(query);
  
  var head = {
    'Developer-token' : "<Dev token>",
    'login-customer-id' : <Manager ID>,
    'Authorization' : "Bearer <Auth token>",
  };

var options = {
  'method' : 'POST',
  'content-type': 'application/json',
  'headers' : head,
  'payload' : body,
  'muteHttpExceptions' : true
};
  
var response = UrlFetchApp.fetch('https://googleads.googleapis.com/v4/customers/<Customer ID>/googleAds:searchStream', options);
  var json = response.getContentText();
  var data = JSON.parse(json);

但我经常收到错误:

"error": {
    "code": 400,
    "message": "Invalid JSON payload received. Unknown name \"{\"query\":\"SELECT campaign.name, campaign.status FROM campaign ORDER BY campaign.id\"}\": Cannot bind query parameter. Field '{\"query\":\"SELECT campaign' could not be found in request message.",
    "status": "INVALID_ARGUMENT",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.BadRequest",
        "fieldViolations": [
          {
            "description": "Invalid JSON payload received. Unknown name \"{\"query\":\"SELECT campaign.name, campaign.status FROM campaign ORDER BY campaign.id\"}\": Cannot bind query parameter. Field '{\"query\":\"SELECT campaign' could not be found in request message."

我已经在 OAuth 游乐场 (https://developers.google.com/oauthplayground) 中运行了查询,它在那里工作,所以我知道查询没问题。

我尝试将正文作为对象而不是字符串传递,但随后出现 500 错误。

【问题讨论】:

  • 您会感到惊讶(但可能很久以前就已经解决了),但问题在于content-type 选项。没有这样的选项 - 正确的选项是 contentType,否则负载类型默认为 application/x-www-form-urlencoded。您对有效负载进行字符串化也是正确的 - 它始终作为字符串传递。但是当 content-type 标头设置为默认值(urlencoded)时,UrlFetchApp 允许您传递一个对象并在后台将其字符串化,但是对于查询,导致 Ads API 服务器无法处理有效负载(因此500 错误)
  • 它确实适用于内容类型(可能两者都适用?但肯定适用于内容类型)。我确实解决了它,所以在下面发布了完整的解决方案。感谢您提醒我跟进!
  • 这很奇怪,参数不能正常工作(除非 API 也接受表单编码的主体,坦率地说,我没有测试)。回复:解决方案 - 你绝对可以删除“查询”部分 - 没关系,在 JS 中,带引号和不带引号的键之间存在 0 差异 - 它们被字符串化相同。我认为该解决方案有效,因为您将内容类型移动到标题 - 它是一个有效的标题(基本上,contentType 选项将此标题设置在幕后)。开发令牌大写也可能导致了这个问题 - 看起来 API 是区分大小写的。
  • 谢谢!我刚刚测试过,你是对的,contentType 是在 options 中设置的,Content-Type 是在 headers 中设置的。设置任何一个都可以使其工作,但它们不可互换。还测试了“查询”的引号和开发者令牌的大写 - 都不重要。
  • 很高兴您检查了 - 一切都符合预期。引用 100% 与规范无关,contentType 拼写很重要,因为这是一个参数,并且 HTTP 标头在定义上不区分大小写(尽管由于用户代码通常会解释它们,我总是尝试遵循确切的大小写)跨度>

标签: google-apps-script google-api google-ads-api


【解决方案1】:

如果其他人正在寻找这个 - 我确实解决了它。

在 header 中设置时,Content-Type 有破折号,在选项中设置时,contentType 没有。

function basicReport() {
     var query = {
        "query" : "SELECT campaign.name, campaign.status FROM campaign ORDER BY campaign.id"
     };
  
     var body = JSON.stringify(query);
  
     var head = {
        'developer-token' : "<Dev token>",
        'login-customer-id' : "<Manager ID>",
        'authorization' : "Bearer <Auth token>",
        'accept' : 'application/json'
        'Content-Type': 'application/json',
     };

    var options = {
        'method' : 'POST',
        'headers' : head,
        'payload' : body,
        'muteHttpExceptions' : true
    };
  
    var response = UrlFetchApp.fetch('https://googleads.googleapis.com/v4/customers/<Customer ID>/googleAds:searchStream', options);
    var json = response.getContentText();
    var data = JSON.parse(json);

    Logger.log(data);

【讨论】:

    猜你喜欢
    • 2017-11-26
    • 2019-09-15
    • 1970-01-01
    • 2018-07-31
    • 2020-12-01
    • 2015-02-08
    • 2023-04-03
    • 2019-08-04
    • 1970-01-01
    相关资源
    最近更新 更多