This is really bad JSON. The problem is that the dictionaries in the responseData
array do not have consistent keys. The first has keys
"categoryName": "Trending",
"Trending": [
But the second has keys
"categoryName": "Comedy",
"Comedy": [
This means that you don't know the name of the second key until you've pulled out the value of the categoryName
key. So you'll have to stop and do that before you can proceed.
So, let's suppose you have your JSON in a string called json
. Then:
let d1 = try! JSONSerialization.jsonObject(with: json.data(using: .utf8)!)
let a1 = (d1 as! [String:Any])["responseData"]
let d2 = (a1 as! [[String:Any]])[1]
let key = d2["categoryName"] as! String // "Comedy"
let a2 = d2[key]!
var d3 = (a2 as! [[String:Any]])[0]
// ["isWatchlist": <null>, "trailerPrice": , "isFavourit": <null>, "category": Comedy]
Now d3
is the inner dictionary you are looking for and you can modify it as desired.
By the way, this your JSON is a nice example of why this is all going to be so much nicer in Swift 4. We can parse the whole JSON into the properties of a custom struct:
struct MyJson : Decodable {
let error : Bool
let error_msg : String
let Total_category : Int
let responseData : [ResponseData]
struct ResponseData : Codable {
let categoryName : String
let unknown : [Inner]
struct Inner : Codable {
let category : String
let trailerPrice : String
let isFavourit : String?
let isWatchList : String?
}
private struct CK : CodingKey {
var stringValue: String
init?(stringValue: String) { self.stringValue = stringValue }
var intValue: Int?
init?(intValue: Int) { return nil }
}
init(from decoder: Decoder) throws {
let con = try! decoder.container(keyedBy: CK.self)
self.categoryName = try! con.decode(String.self, forKey:CK(stringValue:"categoryName")!)
let key = self.categoryName
self.unknown = try! con.decode([Inner].self, forKey: CK(stringValue:key)!)
}
}
}
Having configured our struct, parsing the entire JSON is just one line of code! Assume your JSON is in a variable called json
:
let myjson = try JSONDecoder().decode(MyJson.self, from: json.data(using: .utf8)!)
And the value you are trying to access is expressible very simply:
let fav = myjson.responseData[1].unknown[0].isFavourit
So all I have to do is make all my let
into var
and now they are all settable, as you trying to do.
(For more about this solution, see Swift 4 Decodable with keys not known until decoding time.)