如何修复来自 Google Ads API 的无效 JSON 负载错误

Posted

技术标签:

【中文标题】如何修复来自 Google Ads API 的无效 JSON 负载错误【英文标题】:How to fix Invalid JSON payload error from the Google Ads API 【发布时间】: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 标头在定义上不区分大小写(尽管由于用户代码通常会解释它们,我总是尝试遵循确切的大小写)跨度> 【参考方案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);

【讨论】:

以上是关于如何修复来自 Google Ads API 的无效 JSON 负载错误的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 Google Analytics API 获取 Google Ads 关键字和广告内容

如何通过 Google Ads API 获取已注销的帐户?

如何通过 Google Ads API 检索给定广告系列的受众

如何从 Google Ads API 获取所有帐户树?

如何在 google ads api 中设置请求标头

如何在 Google Ads API 中查询最近停用的广告系列