Home > Mobile >  Swift JSON object with name of something/Integer
Swift JSON object with name of something/Integer

Time:11-11

I'm using TMDB api and fetching tv show seasons, but seasons I get back are not inside array, but as objects with names: season/1, season/2. I need to be able to parse tv show with any number of seasons

Is there a way I can convert this to array without worring about how many seasons does the show have?

struct Result: Codable {
    var season1: Season?
    var season2: Season?
    var id: Int?

    enum CodingKeys: String, CodingKey {
        case season1
        case season2
        case id
    }
}

struct Season: Codable {
    var id: Int?

    enum CodingKeys: String, CodingKey {
        case id
    }
}
{
"id" : 1234,
"season/1": {
  "id": 1234
   },
"season/2": {
  "id": 12345
   }
}

EDIT: Found a solution in dynamic coding keys

private struct DynamicCodingKeys: CodingKey {
       
        var stringValue: String
        init?(stringValue: String) {
            self.stringValue = stringValue
        }

        var intValue: Int?
        init?(intValue: Int) {
            return nil
        }
    }

init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: DynamicCodingKeys.self)

        var tempArray = [TestSeason]()

        for key in container.allKeys {
            if key.stringValue.contains("season/") {
                let decodedObject = try container.decode(TestSeason.self, forKey: DynamicCodingKeys(stringValue: key.stringValue)!)
                tempArray.append(decodedObject)
            } else {
                print("does not contain season \(key.stringValue)")
            }
        }
        season = tempArray
    }

CodePudding user response:

You're getting back a Dictionary, which you can access directly without using your Results struct. The dictionary probably provides a more flexible way of accessing the data than an array, but can also easily be converted to an Array.

As you haven't stated how you'd like the output, the below will convert them to an array of tuples, where each tuple is (season, id)

let data = json.data(using: .utf8)!

let decoder = JSONDecoder()

do {
   let results = try decoder.decode([String:Season].self, from: data)
      .map{($0.key, $0.value.id )}
   print(results) // [("season/2", 12345), ("season/1", 1234)]
} catch {
   print(error)
}

Edit: You also don't need the CodingKeys in Season as it can be inferred from the properties. All you need is

struct Season: Codable {
   let id: Int
}
  • Related