Search code examples
iosjsonswiftalamofireobjectmapper

How to access a link embedded in a JSON dictionary using AlamoFire/ ObjectMapper?


This is the objectmapper I'm using:

ObjectMapper / AlamoFireObjctMapper

Here is the JSON data I'm working with, I'm trying to access the "link" value:

channels =     (
  {
    social =             {
      facebook =                 {
        "facebook_id" = 47360808996;
        link = "https://www.facebook.com/CBS";
      };
      twitter =                 {
        link = "https://twitter.com/CBS";
        "twitter_id" = 97739866;
      }
    }
  }
)

I've created custom objects to represent each level of the JSON dictionary:

class SocialInfo: Mappable {

  var channels: Social?

  required init?(map: Map) {
  }

  func mapping(map: Map) {

    channels <- map["channels"]

  }
}

class Social: Mappable {

  var facebookSocial: Facebook?
  var twitterSocial: Twitter?


  required init?(map: Map) {
  }

  func mapping(map: Map) {

     facebookSocial <- map["facebook"]
     twitterSocial <- map["twitter"]

  }

}


class Facebook: Mappable {

  var facebookLink: NSURL?

  required init?(map: Map) {
  }

  func mapping(map: Map) {

    facebookLink <- (map["link"], URLTransform())

  }
}

Initialy I had the "facebookLink" under the "Facebook" class as a string but it kept returing nil. I then tried the URLTransform to change it to a type of NSURL but now it's throwing the error:

Type of expression is ambiguous without more context

Here is how I'm trying to retrieve the JSON data:

 func getSocialInfo (completionHandler: @escaping (SocialInfo?, Error?) -> ()){

    Alamofire.request("\(baseURL)/\(apiKey)/show/950", method: .get, encoding: JSONEncoding.default).validate ()
      .responseObject{  (response: DataResponse<SocialInfo>) in

        switch response.result {
        case .success:
          let socialInfo = response.result.value

          print("This is the social info: \(socialInfo?.channels?.facebookSocial?.facebookLink)")


          completionHandler(socialInfo!, nil)

        case .failure(let error):

          print("Sorry there was an error: \(error)")
          completionHandler(nil,error)
          return
        }

  }
}

Solution

  • Try setting the link as a string

    var stringURL:String?
    

    Getting the link

    stringURL <- map["link"]
    

    Convert the stringURL to URL

    if let url = URL(string: stringURL) {
    // do something 
    }
    

    Also, note that this will not work, as you are particularly saying that the facebookDictionary is = to your Facebook object.

     class Social: Mappable {
    
      var facebookSocial: Facebook?
      var twitterSocial: Twitter?
    
      fileprivate var facebookDictionary:[AnyHashable:Any]? 
      fileprivate var twitterDictionary:[AnyHashable:Any]?
      required init?(map: Map) {
      }
    
      func mapping(map: Map) {
    
         facebookDictionary <- map["facebook"]
         twitterDictionary <- map["twitter"]
    
         if let _facebookDictionary = facebookDictionary,
            let _twitterDictionary = wittertDictionary {
    
            let twitterMap = Map(mappingType: .fromJSON, JSON: _twitterDictionary)
            let facebookMap = Map(mappingType: .fromJSON, JSON: _facebookDictionary)
    
         /// Here you can initiate both object using map.
    
            facebookSocial = Facebook(map: facebookMap)
            twitterSocial = Twitter(map: twitterMap)
    
        /// If you want to use mapping function, set this as:
    
            facebookSocial = Facebook()
            twitterSocial.mapping(map: twitterMap)
    
            facebookSocial = Facebook()
            twitterSocial.mapping(map: twitterMap)
         }
    
      }
    
    }
    

    As you did not create a new map using the social dictionary, both objects will always be nil

    Same for Social, first create a map out of Social dictionary.