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.

+3


source to share


2 answers


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.

+1


source


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

      

+1


source







All Articles