首页 > 解决方案 > 我的 FCM http 请求仍然有问题

问题描述

我只是希望能够向订阅了某个主题的用户发送通知而没有错误。

这是我用来尝试实现此目标的功能:

 func sendNotificationToUser(to topic: String, title: String, body: String) {
   
    let urlString = "https://fcm.googleapis.com/v1/projects/projectname-41f12/messages:send HTTP/1.1"
    guard let encodedURLString = urlString.addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed) else { return }
    let url = URL(string: encodedURLString)!
    
    struct PostBody: Codable {
        struct Message: Codable {
            let topic: String
            let notification: [[String: String]]
        }
        let message: Message
    }
    
    let postBody = PostBody(message: PostBody.Message(topic: topic,
                                                      notification: [
                                                        ["title": title],
                                                        ["body": body]
                                                                                ]))
    
    
   let encoder = JSONEncoder()
    encoder.outputFormatting = .prettyPrinted
    
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.httpBody = try? encoder.encode(postBody)
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    request.setValue("Bearer ya29.\(self.bearer)", forHTTPHeaderField: "Authorization")
    let task = URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in
        do {
            if let jsonData = data {
                if let jsonDataDictionary = try JSONSerialization.jsonObject(with: jsonData, options: JSONSerialization.ReadingOptions.allowFragments) as? [String: AnyObject] {
                    NSLog("Received data:\n\(jsonDataDictionary))")
                }
                
            }
        } catch let err as NSError {
            print(err)
            print(postBody.message)
            
        }
    }
    task.resume()
}

这是我在按下按钮后调用它的功能:

 getTheSchoolID { (id) in
            if let id = id {
                self.sendNotificationToUser(to: id, title: "New Event Added!", body: "A new event has been added to the dashboard!!")

            }
        }

当我按下按钮时,我不断收到一个 NSCocoaError 并且我仍然这样做,所以我做了我的研究并将我的 JSON 通过jsonlint.com并通过简单地将括号更改为大括号并在对象周围添加双引号来验证它。现在,当我在 Swift 中运行它时,会出现如下错误:

错误

JSON数据打印在错误之间,我看不到JSON有什么问题,我的http请求有问题吗?

编辑我想要的 JSON 结构:

json结构

标签: jsonswifthttp-headersfirebase-cloud-messagingnsdictionary

解决方案


JSON 无效 - 您正在以一种不适用于大多数工具的方式混合字典和数组。您需要将您的 dicts 嵌入到 {...} 中。以下修改(扩展/缩进到最大以显示结构)有效,据我所知是相同的结构:

{
  "message": [
    {
      "topic": "23452345234"
    },
    {
      "notification": [
        {
          "body": "messsage"
        },
        {
          "title": "new event"
        }
      ]
    }
  ]
}

如果由于某种原因你想要一个数组而不是一个字典,那么将上述所有内容嵌入方括号中以获得单个项目数组。

但是,我可能会使用临时结构来生成主体,然后依靠Encodable为我完成工作。下面是一个粗略的解决方案(有很多事情可以改进 - 不是硬编码 dict 键,传入一个形成的 dict,正确处理来自编码器的错误等,......)但希望这会让你开始。

func sendNotificationToUser(to topic: String, title: String, body: String) {
   
   struct PostBody: Codable {
      struct Message: Codable {
         let topic: String
         let notification: [String: String]
      }
      let message: Message
   }

   // generate the request...

   let postBody = PostBody(message: PostBody.Message(
                              topic: topic,
                              notification: [
                                 "title": title,
                                 "body": body ]
                              ) 
                             )
   
   let encoder = JSONEncoder()
   encoder.outputFormatting = .prettyPrinted
   request.httpBody = try? encoder.encode(postBody)

   // finish request, completion handler, etc, etc
}

生成的 JSON 是

{
  "message" : {
    "topic" : "topictext",
    "notification" : {
      "title" : "titleText",
      "body" : "bodyText"
    }
  }
}

推荐阅读