【问题标题】:How do I serialize data into a JSON object如何将数据序列化为 JSON 对象
【发布时间】:2015-12-13 22:33:00
【问题描述】:

我尝试将 JSON 发布到我的 Web 服务器,但它根本不起作用。它适用于 "DELETE" 和 "GET" ,但对于 "POST" 它根本不起作用并获取错误。

这是我的代码:

 let postsEndpoint:String = "http://ideabase.herokuapp.com/categories"
    guard let postsURL = NSURL(string: postsEndpoint) else {
        print("Error: cannot create URL")
        return
    }
    let postsUrlRequest = NSMutableURLRequest(URL: postsURL)
    postsUrlRequest.HTTPMethod = "POST"

    let newPost: NSDictionary = ["id":7, "title": "Purple","created_at": "2015-12-08 08:06:55","updated_at":"2015-12-08 08:06:55"]
    do {
        let jsonPost = try NSJSONSerialization.dataWithJSONObject(newPost, options: [])
        postsUrlRequest.HTTPBody = jsonPost

        let config = NSURLSessionConfiguration.defaultSessionConfiguration()
        let session = NSURLSession(configuration: config)

        let createTask = session.dataTaskWithRequest(postsUrlRequest, completionHandler: {
            (data, response, error) in
            guard let responseData = data else {
                print("Error: did not receive data")
                return
            }
            guard error == nil else {
                print("error calling GET on /categories/1")
                print(error)
                return
            }
            // parse the result as JSON, since that's what the API provides
            let post: NSDictionary
            do {
                post = try NSJSONSerialization.JSONObjectWithData(responseData,
                    options: []) as! NSDictionary
            } catch  {
                print("error parsing response from POST on /categories")
                return
            }
            // now we have the post, let's just print it to prove we can access it
            print("The post is: " + post.description)

            // the post object is a dictionary
            // so we just access the title using the "title" key
            // so check for a title and print it if we have one
            if let postID = post["id"] as? Int
            {
                print("The ID is: \(postID)")
            }
        })
        createTask.resume()

我收到错误“从 /categories 上的 POST 解析响应”

你能帮帮我吗?

【问题讨论】:

  • 尝试使用 Charles 或其他允许您查看所有进出系统的 http 流量的代理。然后,您可以确保帖子是您所期望的,并查看回复的详细信息。
  • @Gharay,我添加了一个工作 POST 请求的示例

标签: json swift serialization swift2


【解决方案1】:

你说:

我尝试将 JSON 发布到我的网络服务器,但它根本不起作用

在查看您的代码时,我们确定有两件事。

  1. 你有数据,否则你的守卫会回来。
  2. 您没有出错,否则您的第二个守卫会返回。

你正在把它归结为你的 NSJSONSerialization,所以在这之前你都很好。现在你只需要调整你的序列化类型,你应该(也许)很好。

您需要将您的 post 类型更改为 [[String:AnyObject]],因为我们将在您的 try catch 中作为您的演员。

 let post: [[String:AnyObject]]
 do {
     post = try NSJSONSerialization.JSONObjectWithData(responseData,
                    options: .MutableLeaves) as! [[String:AnyObject]]
 } catch  {
     print("error parsing response from POST on /categories")
     return
 }

当你这样做时,很容易通过将你的帖子传递给这样的函数来获取你的返回值:

func valuesFromData(jsonDict: [[String:AnyObject]]) {
    let myValue = jsonDict["key"] as? String
    let another = jsonDict["SomeOtherKey"] as? Int
}

如果您仍然遇到问题,您只需打印出我们的状态代码,看看您的 POST 为何无法正常工作。在完成处理程序(闭​​包)中添加以下内容:

guard let status = response.statusCode as? NSHTTPURLResponse else {
    return
}
print("status code: \(status)")

这是一个完美运行的 NSURLRequest 示例

func postNewMessage(messageType: String, messageBody: String) {

        guard let token = AppDelegate.userDefaults.valueForKey("token") else {
            return
        }

        let params = [
            "messageType": messageType,
            "messageBody": messageBody
        ]

        var jsonData: NSData?
        var jsonString: NSString?
        var tokenResponse: String?

        do {
            jsonData = try NSJSONSerialization.dataWithJSONObject(params, options: [])
        } catch {
            print(error)
            return
        }

        let request = NSMutableURLRequest(URL: NSURL(string: "http://localhost:8080/messages")!)
        let session = NSURLSession.sharedSession()

        request.HTTPMethod = "POST"
        request.addValue(token as! String, forHTTPHeaderField: "user-auth-token")
        request.HTTPBody = jsonData!
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.addValue("application/json", forHTTPHeaderField: "Accept")

        let task = session.dataTaskWithRequest(request) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in

            guard let testResponse = response as? NSHTTPURLResponse else {
                print("failed \(response)")
                return
            }

            guard let status = HTTPStatusCodes(rawValue: testResponse.statusCode) else {
                print("failed again")
                return
            }

            switch status {
            case .Created:
                let headerFields = testResponse.allHeaderFields
                tokenResponse = headerFields["user-auth-token"] as? String
                guard let returnedData = data else {
                    print("no data was returned")
                    break
                }
                // convert data to string
                jsonString = NSString(data: returnedData, encoding: NSUTF8StringEncoding) ?? "Invalid JSON"
                print("\(tokenResponse)\n\n\(jsonString!)")

                // update user interface
                dispatch_sync(dispatch_get_main_queue()) {
                    print("derp")
                }

            default:
                print("asdf")
            }
        }
        task.resume()
    }

您还需要拥有此枚举才能使其工作。

enum HTTPStatusCodes : Int {
    case Ok = 200
    case Created = 201
    case BadRequest = 404
}

(简体)

【讨论】:

  • 我试过了,但还是不行,而且响应没有 statusCode 成员!它给我一个错误
  • @Gharary 我添加了一个完全可操作的 NSURLSession 供您比较您的代码
猜你喜欢
  • 2021-05-29
  • 2018-09-08
  • 2014-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多