我的 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 中运行它时,出现如下错误

errors

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

编辑我想要的 JSON 结构:

json structure

解决方法

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"
    }
  }
}