не может отправить запрос в Swift 4 - PullRequest
0 голосов
/ 19 ноября 2018

не может обработать запрос POST, но не может понять, почему, структура является Codable, и в url нет ошибки.Я получаю это сообщение об ошибке в консоли

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** +[NSJSONSerialization dataWithJSONObject:options:error:]: Invalid top-level type in JSON write'
*** First throw call stack:
(0x1ac0dfea0 )
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) 

, но все выглядит нормально

моя структура:

struct PostOfMine: Codable {
    let body: String?
    let id: Int?
    let title: String?
    let userId: Int?
}

моя функция:

func postData() {
    guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else {
        print("WARNING: url related error")
        return}
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.addValue("Application/json", forHTTPHeaderField: "Content-Type")

    let newPost = PostOfMine(body: "test body", id: 20, title: "test title", userId: 20)

    do {
        let jsonBody = try JSONSerialization.data(withJSONObject: newPost, options: [])
        request.httpBody = jsonBody
    } catch {
        print(error.localizedDescription)
    }

let session = URLSession.shared
let task = session.dataTask(with: request) { (Data, _, error) in
    guard let data =  Data else {return}
    do {
        let sentPost = try JSONSerialization.jsonObject(with: data, options: [])
        print(sentPost)
    } catch {
        print(error.localizedDescription)
    }
}
task.resume()

}

Ответы [ 2 ]

0 голосов
/ 19 ноября 2018

Согласно документам Apple:

JSONSerialization.data (withJSONObject: obj, параметры: [])

Если obj не выдаст действительный JSON, исключение составляетвыброшены.Это исключение выдается перед анализом и представляет собой ошибку программирования, а не внутреннюю ошибку.Вы должны проверить, будет ли ввод генерировать допустимый JSON, прежде чем вызывать этот метод, используя isValidJSONObject (_:).

В вашем коде исключение вызвано по причине ниже

  1. JSONSerialization.data (withJSONObject: obj, options: []) В этом методе вы должны передать действительный объект JSON, например, obj.Вы просто подтверждаете кодируемый протокол и передаете структурную переменную вместо объекта JSON.

Код:

struct PostOfMine: Codable {
    let body: String?
    let id: Int?
    let title: String?
    let userId: Int?

   private enum CodingKeys: String, CodingKey {
        case body
        case id
        case title
        case userId
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(body, forKey: .body)
        try container.encode(id, forKey: .id)
        try container.encode(title, forKey: .title)
        try container.encode(userId, forKey: .userId)
    }
}


override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    let newPost = PostOfMine(body: "test body", id: 20, title: "test title", userId: 20)
    do {
        let encoder = JSONEncoder()
        let newPostData = try encoder.encode(newPost)
       //Send newPostData to your server.
        request.httpBody = newPostData
//Send data you your server


        //For Decoding the data use JSONDecoder
        let post = try JSONDecoder().decode(PostOfMine.self, from: newPostData)
        debugPrint(post)
    } catch {
        debugPrint(error.localizedDescription)
    }
}
0 голосов
/ 19 ноября 2018

Поскольку ваша модель соответствует Codable, вы получаете JSONEncoder().encode(_:) бесплатно. Используйте это для кодирования вместо JSONSerialization

func postData() {

//...

//For this particular api, the server will take care of generating an `id` so leave that as `nil`

  let newPost = PostOfMine(body: "test body", id: nil, title: "test title", userId: 20)

    do { 
    let jsonBody = try JSONEncoder().encode(newPost)

    } catch {
    print(error.localizedDescription)
    }

let session = URLSession.shared
session.dataTask(with: request) { _, response, error in 

if error != nil { 
//check & handle error from upload task. 
} 

if let response = response as? HTTPURLResponse {

 // Monitor the status code recieved from the server. 200-300 = OK
    print(response.statusCode)
 // prints 201 - Created

      }
  }.resume()

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...