SwiftyJD
SwiftyJD

Reputation: 5441

How to properly create objects from a JSON dictionary that start with a numbers instead of strings?

I'm having a tough time creating objects from the JSON below. It's weirdly formatted with = and ; but that's how it looks when printed to console:

 result =     (
    {
 media =             {
        image =                 {
          1000 = "/assets/img/cities/basel-switzerland-1000px.jpg";
          1500 = "/assets/img/cities/basel-switzerland-1500px.jpg";
          250 = "/assets/img/cities/basel-switzerland-250px.jpg";
          500 = "/assets/img/cities/basel-switzerland-500px.jpg";
        };
      };
}
)

I've created custom objects but I keep getting a

EXC_BAD_INSTRUCTION

error when I use [Int: Any] for the "image" and when I substitute NSNumber instead I get an error:

Could not cast value of type 'NSTaggedPointerString' (0x10ee4ad10) to 'NSNumber' (0x10bc88488).

Here is my custom class for the JSON objects:

class sampleJSON {
  var mediaDictionary: [String: Any]
  var imageDictionary: [Int: Any]
  var image: URL

  init( mediaDictionary: [String: Any], imageDictionary: [Int: Any], image: URL){
    self.mediaDictionary = mediaDictionary
    self.imageDictionary = imageDictionary
    self.image = image
  }

  init(resultsDictionary:[String: Any]){
    mediaDictionary = (resultsDictionary["media"] as? [String: Any])!
    imageDictionary = (mediaDictionary["image"] as? [Int: Any])!
    image = URL(string: imageDictionary[1000] as! String)!
  }

This is how I'm parsing the JSON data:

static func downloadAllData(urlExtension: String, completionHandler: @escaping (sampleJSON?) -> ()) {
    let usm = UrlSessionNetworkManager.sharedManager

    if let jsonDictionary = usm.parseJSONFromData(urlExtension:"\(urlExtension)")
    {
      let resultDictionaries = jsonDictionary["result"] as! [[String : Any]]
      for resultsDictionary in resultDictionaries {// enumerate through dictionary
        let nomadInfo = sampleJSON(resultsDictionary: resultsDictionary)

        print(nomadInfo.mediaDictionary)

        completionHandler(nomadInfo)
      }
    } else {
      print("Error: Cannot retrieve JSON Data")
    }
  }
}

Upvotes: 1

Views: 46

Answers (1)

Coder-256
Coder-256

Reputation: 5618

Replace all occurences of [Int: Any] with [String: Any], and make that change in the server code, too. As mentioned by @Paulw11, JSON keys can only be strings (but a value can be a string in double quotes, or a number, or true or false or null, or an object or an array). Also, as I mentioned, never use (a as? b)!, instead use a as! b.

The new (and now valid) JSON should look like:

 result =     (
    {
 media =             {
        image =                 {
          "1000" = "/assets/img/cities/basel-switzerland-1000px.jpg";
          "1500" = "/assets/img/cities/basel-switzerland-1500px.jpg";
          "250" = "/assets/img/cities/basel-switzerland-250px.jpg";
          "500" = "/assets/img/cities/basel-switzerland-500px.jpg";
        };
      };
}
)

The custom class should be:

class sampleJSON {
  var mediaDictionary: [String: Any]
  var imageDictionary: [String: Any]
  var image: URL

  init( mediaDictionary: [String: Any], imageDictionary: [String: Any], image: URL){
    self.mediaDictionary = mediaDictionary
    self.imageDictionary = imageDictionary
    self.image = image
  }

  init(resultsDictionary:[String: Any]){
    mediaDictionary = resultsDictionary["media"] as! [String: Any]
    imageDictionary = mediaDictionary["image"] as! [String: Any]
    image = URL(string: imageDictionary["1000"] as! String)!
  }

And the parsing function should be (just a small, unrelated issue fixed):

static func downloadAllData(urlExtension: String, completionHandler: @escaping (sampleJSON?) -> ()) {
    let usm = UrlSessionNetworkManager.sharedManager

    if let jsonDictionary = usm.parseJSONFromData(urlExtension: urlExtension)
    {
      let resultDictionaries = jsonDictionary["result"] as! [[String : Any]]
      for resultsDictionary in resultDictionaries {// enumerate through dictionary
        let nomadInfo = sampleJSON(resultsDictionary: resultsDictionary)

        print(nomadInfo.mediaDictionary)

        completionHandler(nomadInfo)
      }
    } else {
      print("Error: Cannot retrieve JSON Data")
    }
  }
}

Upvotes: 0

Related Questions