{"id":854,"date":"2014-06-18T09:25:59","date_gmt":"2014-06-18T15:25:59","guid":{"rendered":"http:\/\/jamesonquave.com\/blog\/?p=854"},"modified":"2020-05-10T18:56:11","modified_gmt":"2020-05-11T00:56:11","slug":"making-a-post-request-in-swift","status":"publish","type":"post","link":"https:\/\/jamesonquave.com\/blog\/making-a-post-request-in-swift\/","title":{"rendered":"Making a POST request in Swift"},"content":{"rendered":"<p><i><strong>This post updated September 16 for Xcode 6 GM<\/strong><\/i><\/p>\n<p>Let&#8217;s say you&#8217;re working on an iOS app where you need to pass data to a server as JSON. Just about every app that interacts with a server does this, and almost always there is a login API call.<\/p>\n<p>For the purposes of this tutorial, I&#8217;m first going to set up a super simple web server that handles a POST request. This part of the tutorial is optional if you already have a server, and you can <a href=\"#jumpSwift\">skip ahead to the Swift code<\/a>. Go ahead and create a ruby file called api.rb, and stick this in there:<\/p>\n<p>Note: Alternatively, you could use tasty with a <a href=\"https:\/\/crunchskills.com\/deno-web-server-and-api-tutorial\/\">Deno web server<\/a> here, which is more similar to Swift than NodeJS.<\/p>\n<p><code><br \/>\n#!\/usr\/bin\/env ruby<br \/>\nrequire 'rubygems'<br \/>\nrequire 'sinatra'<br \/>\nrequire 'json'<br \/>\nget '\/' do<br \/>\n\"Nothing to see here. Move along.\"<br \/>\nend<br \/>\npost '\/login' do<br \/>\nvalues = JSON.parse(request.env[\"rack.input\"].read)<br \/>\nif values[\"username\"]=='jameson' &amp;&amp; values[\"password\"]=='password'<br \/>\n\"{\\\"success\\\":1}\"<br \/>\nelse<br \/>\n\"{\\\"success\\\":0}\"<br \/>\nend<br \/>\nend<br \/>\n<\/code><\/p>\n<p>Now, I know this is ruby code but it&#8217;s just to get us a server up and running fast. To run this you&#8217;ll first need to make it executable. Open up a Terminal window and cd to the directory where api.rb is, then you can add the executable permission like this:<br \/>\n<code><br \/>\nchmod +x api.rb<br \/>\n<\/code><\/p>\n<p>And you&#8217;ll need the gem:<\/p>\n<p><code><br \/>\ngem install sinatra<br \/>\ngem install json<br \/>\n<\/code><\/p>\n<p>Depending on your system&#8217;s configuration, this might give you some kind of permissions error. If it does prepend the &#8216;sudo&#8217; statement in front of this:<\/p>\n<p><code><br \/>\nsudo gem install sinatra<br \/>\nsudo gem install json<br \/>\n<\/code><\/p>\n<p><i>Note: You normally want ruby gems to be installed in to a user directory using RVM and a gemset, but this is a Swift tutorial so we&#8217;re just going to keep moving \ud83d\ude42<\/i><\/p>\n<p>Okay now give it a whirl:<br \/>\n<code><br \/>\n.\/api.rb<br \/>\n<\/code><\/p>\n<div id=\"jumpSwift\">\n<p>&nbsp;<br \/>\nYou should now have a web server up and running that accepts a POST call to \/login. The server by default runs on port 4567, so now let&#8217;s create a Swift project to interact with it. A simple single-view project is fine for this example.<\/p>\n<p>In your application didFinishLaunchingWithOptions method add the following:<\/p>\n<pre class=\"brush: js;\">func application(application: UIApplication!, didFinishLaunchingWithOptions launchOptions: NSDictionary!) -&gt; Bool {\r\n    var request = NSMutableURLRequest(URL: NSURL(string: \"http:\/\/localhost:4567\/login\"))\r\n    var session = NSURLSession.sharedSession()\r\n    request.HTTPMethod = \"POST\"\r\n    \r\n    var params = [\"username\":\"jameson\", \"password\":\"password\"] as Dictionary&lt;String, String&gt;\r\n    \r\n    var err: NSError?\r\n    request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &amp;err)\r\n    request.addValue(\"application\/json\", forHTTPHeaderField: \"Content-Type\")\r\n    request.addValue(\"application\/json\", forHTTPHeaderField: \"Accept\")\r\n    \r\n    var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -&gt; Void in\r\n        println(\"Response: \\(response)\")\r\n        var strData = NSString(data: data, encoding: NSUTF8StringEncoding)\r\n        println(\"Body: \\(strData)\")\r\n        var err: NSError?\r\n        var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &amp;err) as? NSDictionary\r\n        \r\n        \/\/ Did the JSONObjectWithData constructor return an error? If so, log the error to the console\r\n        if(err != nil) {\r\n            println(err!.localizedDescription)\r\n            let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)\r\n            println(\"Error could not parse JSON: '\\(jsonStr)'\")\r\n        }\r\n        else {\r\n            \/\/ The JSONObjectWithData constructor didn't return an error. But, we should still\r\n            \/\/ check and make sure that json has a value using optional binding.\r\n            if let parseJSON = json {\r\n                \/\/ Okay, the parsedJSON is here, let's get the value for 'success' out of it\r\n                var success = parseJSON[\"success\"] as? Int\r\n                println(\"Succes: \\(success)\")\r\n            }\r\n            else {\r\n                \/\/ Woa, okay the json object was nil, something went worng. Maybe the server isn't running?\r\n                let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)\r\n                println(\"Error could not parse JSON: \\(jsonStr)\")\r\n            }\r\n        }\r\n    })\r\n    \r\n    task.resume()\r\n    return true\r\n}\r\n<\/pre>\n<p>First we create a request and a session to operate on.<br \/>\nNext, we set some params in a Swift dictionary, these values will be passed to the server.<\/p>\n<p>Using dataWithJSONObject() we can encode our parameters as NSData, and set the HTTPBody of the request to this NSData object.<\/p>\n<p>Next we add our headers stating we&#8217;re working with JSON using addValue()<\/p>\n<p>Finally we instantiate a NSTask from the NSURLSession object with dataTaskWithRequest()<\/p>\n<p>The last parameter of dataTaskWithRequest is a closure that contains values for the response, data, or error from our server.<\/p>\n<p>After deserializing the response with JSONObjectWithData(), we can check json[&#8220;success&#8221;] for the 0 or 1 coming back from our server to see if the request succeeded, and process the results.<\/p>\n<p>Most of this is just boilerplate, so it&#8217;s useless to move this all out in to a new function, we&#8217;ll call it post().<\/p>\n<p>Move all the post logic out to this method, taking params and url as arguments.<\/p>\n<pre class=\"brush: js;\">func post(params : Dictionary&lt;String, String&gt;, url : String) {\r\n    var request = NSMutableURLRequest(URL: NSURL(string: url))\r\n    var session = NSURLSession.sharedSession()\r\n    request.HTTPMethod = \"POST\"\r\n    \r\n    var err: NSError?\r\n    request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &amp;err)\r\n    request.addValue(\"application\/json\", forHTTPHeaderField: \"Content-Type\")\r\n    request.addValue(\"application\/json\", forHTTPHeaderField: \"Accept\")\r\n    \r\n    var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -&gt; Void in\r\n        println(\"Response: \\(response)\")\r\n        var strData = NSString(data: data, encoding: NSUTF8StringEncoding)\r\n        println(\"Body: \\(strData)\")\r\n        var err: NSError?\r\n        var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &amp;err) as? NSDictionary\r\n        \r\n        \/\/ Did the JSONObjectWithData constructor return an error? If so, log the error to the console\r\n        if(err != nil) {\r\n            println(err!.localizedDescription)\r\n            let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)\r\n            println(\"Error could not parse JSON: '\\(jsonStr)'\")\r\n        }\r\n        else {\r\n            \/\/ The JSONObjectWithData constructor didn't return an error. But, we should still\r\n            \/\/ check and make sure that json has a value using optional binding.\r\n            if let parseJSON = json {\r\n                \/\/ Okay, the parsedJSON is here, let's get the value for 'success' out of it\r\n                var success = parseJSON[\"success\"] as? Int\r\n                println(\"Succes: \\(success)\")\r\n            }\r\n            else {\r\n                \/\/ Woa, okay the json object was nil, something went worng. Maybe the server isn't running?\r\n                let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)\r\n                println(\"Error could not parse JSON: \\(jsonStr)\")\r\n            }\r\n        }\r\n    })\r\n    \r\n    task.resume()\r\n}\r\n<\/pre>\n<p>Now our main logic can be greatly simplified for making any POST request. Let&#8217;s make a couple in the didFinishLaunching method.<\/p>\n<pre class=\"brush: js;\">func application(application: UIApplication!, didFinishLaunchingWithOptions launchOptions: NSDictionary!) -&gt; Bool {\r\n    \r\n    \/\/ Correct url and username\/password\r\n    self.post([\"username\":\"jameson\", \"password\":\"password\"], url: \"http:\/\/localhost:4567\/login\")\r\n    \r\n    \/\/ Correct url, incorrect password\r\n    self.post([\"username\":\"jameson\", \"password\":\"wrong_password\"], url: \"http:\/\/localhost:4567\/login\")\r\n    \r\n    \/\/ Incorrect url\r\n    self.post([\"username\":\"jameson\", \"password\":\"password\"], url: \"http:\/\/badurl.com\/nonexistent\")\r\n\r\n    return true\r\n}\r\n<\/pre>\n<p>In your console you should be able to see three login attempts, with only one of them succeeding. This is all great, but we should probably implement a way for the post request to notify our caller of a success or failure. Let&#8217;s add a Swift closure as a third method parameter to our post() function, so we can call it upon success or completion.<\/p>\n<pre class=\"brush: js;\">func post(params : Dictionary&lt;String, String&gt;, url : String, postCompleted : (succeeded: Bool, msg: String) -&gt; ()) {\r\n<\/pre>\n<p>Now we have our new postCompleted closure, we can pass back to the caller whether or not the post request &#8220;succeeded&#8221;, and a string message to display to the user.<\/p>\n<pre class=\"brush: js;\">func post(params : Dictionary&lt;String, String&gt;, url : String, postCompleted : (succeeded: Bool, msg: String) -&gt; ()) {\r\n    var request = NSMutableURLRequest(URL: NSURL(string: url))\r\n    var session = NSURLSession.sharedSession()\r\n    request.HTTPMethod = \"POST\"\r\n    \r\n    var err: NSError?\r\n    request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &amp;err)\r\n    request.addValue(\"application\/json\", forHTTPHeaderField: \"Content-Type\")\r\n    request.addValue(\"application\/json\", forHTTPHeaderField: \"Accept\")\r\n    \r\n    var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -&gt; Void in\r\n        println(\"Response: \\(response)\")\r\n        var strData = NSString(data: data, encoding: NSUTF8StringEncoding)\r\n        println(\"Body: \\(strData)\")\r\n        var err: NSError?\r\n        var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &amp;err) as? NSDictionary\r\n        \r\n        var msg = \"No message\"\r\n        \r\n        \/\/ Did the JSONObjectWithData constructor return an error? If so, log the error to the console\r\n        if(err != nil) {\r\n            println(err!.localizedDescription)\r\n            let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)\r\n            println(\"Error could not parse JSON: '\\(jsonStr)'\")\r\n            postCompleted(succeeded: false, msg: \"Error\")\r\n        }\r\n        else {\r\n            \/\/ The JSONObjectWithData constructor didn't return an error. But, we should still\r\n            \/\/ check and make sure that json has a value using optional binding.\r\n            if let parseJSON = json {\r\n                \/\/ Okay, the parsedJSON is here, let's get the value for 'success' out of it\r\n                if let success = parseJSON[\"success\"] as? Bool {\r\n                    println(\"Succes: \\(success)\")\r\n                    postCompleted(succeeded: success, msg: \"Logged in.\")\r\n                }\r\n                return\r\n            }\r\n            else {\r\n                \/\/ Woa, okay the json object was nil, something went worng. Maybe the server isn't running?\r\n                let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)\r\n                println(\"Error could not parse JSON: \\(jsonStr)\")\r\n                postCompleted(succeeded: false, msg: \"Error\")\r\n            }\r\n        }\r\n    })\r\n    \r\n    task.resume()\r\n}\r\n<\/pre>\n<p>We&#8217;ll also need to modify how we call the method in our applicationDidFinishLaunching function.<br \/>\nThe last parameter will now be a closure. Using Swift&#8217;s trailing closure syntax we can just end the post call with the block { }<br \/>\nInside of this closure we create an UIAlertView control and populate it based on the succeeded and msg variables.<br \/>\nThen, we move back to a foreground thread and show the alert view.<\/p>\n<pre class=\"brush: js;\">func application(application: UIApplication!, didFinishLaunchingWithOptions launchOptions: NSDictionary!) -&gt; Bool {\r\n    \r\n    \/\/ Correct url and username\/password\r\n    self.post([\"username\":\"jameson\", \"password\":\"password\"], url: \"http:\/\/localhost:4567\/login\") { (succeeded: Bool, msg: String) -&gt; () in\r\n        var alert = UIAlertView(title: \"Success!\", message: msg, delegate: nil, cancelButtonTitle: \"Okay.\")\r\n        if(succeeded) {\r\n            alert.title = \"Success!\"\r\n            alert.message = msg\r\n        }\r\n        else {\r\n            alert.title = \"Failed : (\"\r\n            alert.message = msg\r\n        }\r\n        \r\n        \/\/ Move to the UI thread\r\n        dispatch_async(dispatch_get_main_queue(), { () -&gt; Void in\r\n            \/\/ Show the alert\r\n            alert.show()\r\n        })\r\n    }\r\n\r\n    return true\r\n}\r\n<\/pre>\n<p>Give it a whirl, and can now see a server logging in a user (or failing to) with some UI feedback. Cool right?<\/p>\n<p>Try changing the login information and see what you get.<\/p>\n<p>This is an overly simplistic server but I just wanted to demonstrate how you would go about making a POST request in Swift. I hope it was helpful!<\/p>\n<p>The full source code to this project can be downloaded from Github <a href=\"https:\/\/github.com\/jquave\/SwiftPOSTTutorial\">here<\/a>.<\/p>\n<p>In <a href=\"http:\/\/jamesonquave.com\/swiftebook\/\">my book<\/a> I go in to much more detail, showing how to work with form data and chain API requests together.<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>This post updated September 16 for Xcode 6 GM Let&#8217;s say you&#8217;re working on an iOS app where you need to pass data to a server as JSON. Just about every app that interacts with a server does this, and almost always there is a login API call. For the purposes of this tutorial, I&#8217;m&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_links_to":"","_links_to_target":""},"categories":[25,10,32],"tags":[46,15,39,48,44,45,33,47,43],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v19.13 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Making a POST request in Swift - Jameson Quave<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/jamesonquave.com\/blog\/making-a-post-request-in-swift\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Making a POST request in Swift - Jameson Quave\" \/>\n<meta property=\"og:description\" content=\"This post updated September 16 for Xcode 6 GM Let&#8217;s say you&#8217;re working on an iOS app where you need to pass data to a server as JSON. Just about every app that interacts with a server does this, and almost always there is a login API call. For the purposes of this tutorial, I&#8217;m...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/jamesonquave.com\/blog\/making-a-post-request-in-swift\/\" \/>\n<meta property=\"og:site_name\" content=\"Jameson Quave\" \/>\n<meta property=\"article:published_time\" content=\"2014-06-18T15:25:59+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2020-05-11T00:56:11+00:00\" \/>\n<meta name=\"author\" content=\"Jameson Quave\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jameson Quave\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/jamesonquave.com\/blog\/making-a-post-request-in-swift\/\",\"url\":\"https:\/\/jamesonquave.com\/blog\/making-a-post-request-in-swift\/\",\"name\":\"Making a POST request in Swift - Jameson Quave\",\"isPartOf\":{\"@id\":\"https:\/\/jamesonquave.com\/blog\/#website\"},\"datePublished\":\"2014-06-18T15:25:59+00:00\",\"dateModified\":\"2020-05-11T00:56:11+00:00\",\"author\":{\"@id\":\"https:\/\/jamesonquave.com\/blog\/#\/schema\/person\/db6184f355c7f4e3b876d0f228c2fcfc\"},\"breadcrumb\":{\"@id\":\"https:\/\/jamesonquave.com\/blog\/making-a-post-request-in-swift\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/jamesonquave.com\/blog\/making-a-post-request-in-swift\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/jamesonquave.com\/blog\/making-a-post-request-in-swift\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/jamesonquave.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Making a POST request in Swift\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/jamesonquave.com\/blog\/#website\",\"url\":\"https:\/\/jamesonquave.com\/blog\/\",\"name\":\"Jameson Quave\",\"description\":\"Using computer technology to educate, and improve lives.\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/jamesonquave.com\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/jamesonquave.com\/blog\/#\/schema\/person\/db6184f355c7f4e3b876d0f228c2fcfc\",\"name\":\"Jameson Quave\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/jamesonquave.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/d9786c83345117d560bbeab0e1f26814?s=96&d=retro&r=pg\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/d9786c83345117d560bbeab0e1f26814?s=96&d=retro&r=pg\",\"caption\":\"Jameson Quave\"},\"sameAs\":[\"http:\/\/jamesonquave.com\"],\"url\":\"https:\/\/jamesonquave.com\/blog\/author\/jquave\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Making a POST request in Swift - Jameson Quave","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/jamesonquave.com\/blog\/making-a-post-request-in-swift\/","og_locale":"en_US","og_type":"article","og_title":"Making a POST request in Swift - Jameson Quave","og_description":"This post updated September 16 for Xcode 6 GM Let&#8217;s say you&#8217;re working on an iOS app where you need to pass data to a server as JSON. Just about every app that interacts with a server does this, and almost always there is a login API call. For the purposes of this tutorial, I&#8217;m...","og_url":"https:\/\/jamesonquave.com\/blog\/making-a-post-request-in-swift\/","og_site_name":"Jameson Quave","article_published_time":"2014-06-18T15:25:59+00:00","article_modified_time":"2020-05-11T00:56:11+00:00","author":"Jameson Quave","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Jameson Quave","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/jamesonquave.com\/blog\/making-a-post-request-in-swift\/","url":"https:\/\/jamesonquave.com\/blog\/making-a-post-request-in-swift\/","name":"Making a POST request in Swift - Jameson Quave","isPartOf":{"@id":"https:\/\/jamesonquave.com\/blog\/#website"},"datePublished":"2014-06-18T15:25:59+00:00","dateModified":"2020-05-11T00:56:11+00:00","author":{"@id":"https:\/\/jamesonquave.com\/blog\/#\/schema\/person\/db6184f355c7f4e3b876d0f228c2fcfc"},"breadcrumb":{"@id":"https:\/\/jamesonquave.com\/blog\/making-a-post-request-in-swift\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/jamesonquave.com\/blog\/making-a-post-request-in-swift\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/jamesonquave.com\/blog\/making-a-post-request-in-swift\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/jamesonquave.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Making a POST request in Swift"}]},{"@type":"WebSite","@id":"https:\/\/jamesonquave.com\/blog\/#website","url":"https:\/\/jamesonquave.com\/blog\/","name":"Jameson Quave","description":"Using computer technology to educate, and improve lives.","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/jamesonquave.com\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/jamesonquave.com\/blog\/#\/schema\/person\/db6184f355c7f4e3b876d0f228c2fcfc","name":"Jameson Quave","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/jamesonquave.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/d9786c83345117d560bbeab0e1f26814?s=96&d=retro&r=pg","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d9786c83345117d560bbeab0e1f26814?s=96&d=retro&r=pg","caption":"Jameson Quave"},"sameAs":["http:\/\/jamesonquave.com"],"url":"https:\/\/jamesonquave.com\/blog\/author\/jquave\/"}]}},"_links":{"self":[{"href":"https:\/\/jamesonquave.com\/blog\/wp-json\/wp\/v2\/posts\/854"}],"collection":[{"href":"https:\/\/jamesonquave.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jamesonquave.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jamesonquave.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jamesonquave.com\/blog\/wp-json\/wp\/v2\/comments?post=854"}],"version-history":[{"count":28,"href":"https:\/\/jamesonquave.com\/blog\/wp-json\/wp\/v2\/posts\/854\/revisions"}],"predecessor-version":[{"id":2635,"href":"https:\/\/jamesonquave.com\/blog\/wp-json\/wp\/v2\/posts\/854\/revisions\/2635"}],"wp:attachment":[{"href":"https:\/\/jamesonquave.com\/blog\/wp-json\/wp\/v2\/media?parent=854"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jamesonquave.com\/blog\/wp-json\/wp\/v2\/categories?post=854"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jamesonquave.com\/blog\/wp-json\/wp\/v2\/tags?post=854"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}