Parsing nested JSON with Alamofire 4
So, I've been trying all day to parse JSON from my WordPress API using Alomofire 4, I've tried everything I can find related to my problem, but I still can't seem to solve the problem.
The goal is to just make a request from the API and print it out, from there I can manage, but since JSON seems to have nested arrays / dictionaries, I'm having a hard time figuring out what to use.
My code:
Alamofire.request(_newsURL).responseJSON { response in
print(response.result)
if let json = response.result.value as? [Any] {
print("JSON: \(json)")
}
if let dict = response.result.value as? Dictionary<String, AnyObject>{
print(response.result.value)
if let slug = dict["slug"] as? String {
self._newsSlug = slug
}
print("Hello News")
print(self._newsURL)
print(self._newsSlug)
} else {
print("Found Nothing")
}
}
API: http://www.wsvh.nl/wp-json/wp/v2/posts
My goal is to just call and print stuff like the header (which is also nested even more?). I was trying to get it to only work with the slug, since I was not nested as a rendered header, so I figured I should start with the simplest part, but I can't even get it to work.
Thanks in advance.
source to share
The API returns an array of dictionaries , where each dictionary represents a message like [String: Any]
:
Alamofire.request(_newsURL).responseJSON { response in
if let posts = response.result.value as? [[String: Any]] {
posts.forEach { post in
if let slug = post["slug"] as? String {
print("Slug: \(slug)")
}
if let title = post["title"] as? [String: String] {
print("Title: \(title["rendered"])")
}
if let categories = post["categories"] as? [Int] {
print("Categories: \(categories)")
}
// You can retrieve as many field as you like as above...
}
}
}
I highly recommend that you use an object mapping library such as ObjectMapper
, so you don't have to worry about type checking or casting at all.
Just create a model named Post
:
import ObjectMapper
class Post: Mappable, CustomStringConvertible {
var title: String?
var slug: String?
var link: URL?
var content: String?
required init?(map: Map) {}
func mapping(map: Map) {
title <- map["title.rendered"]
slug <- map["slug"]
link <- (map["link"], URLTransform())
content <- map["content.rendered"]
}
var description: String {
return "Post <\(title ?? "No title")>"
}
}
so you can get all messages like this:
import AlamofireObjectMapper
Alamofire.request("http://www.wsvh.nl/wp-json/wp/v2/posts")
.responseArray { (response: DataResponse<[Post]>) in
// This will give you the array of Post objects.
print("Posts: \(response.result.value)")
}
I created a sample project for you . You can download and play with it to get a better understanding of how the mapping is done.
source to share
For this kind of task, I suggest you use SwiftyJSON . This will help you keep things simple and clean. eg.
Alamofire.request(_newsURL).responseJSON(completionHandler: {
response in
if let value = response.result.value {
let json = JSON(value) //Don't forget to import SwiftyJSON
debugPrint(json)
debugPrint(json[0]["slug"].stringValue) //print value of slug property
debugPrint(json[0]["title"]["rendered"].stringValue) //print nested value of title
}
})
source to share