I have a JSON file that contains details about cryptocurrency with a key that changes (you can see after data there are 1,2 and so on) I did some research and realized that I need to use a dictionary (as defined in struct coin info) the problem is that I get an error - "Expected to decode Dictionary<String, Any> but found a string/data instead.", underlying error: nil))
I would appreciate an explanation of what the problem is and where I am wrong.
my structs:
struct CoinsInfo:Codable {
let data:[String:CoinSpecificInfo]?
}
struct CoinSpecificInfo:Codable {
let urls:UrlsCoins?
let logo:String?
let id:Int?
let symbol:String?
}
struct UrlsCoins:Codable {
let website:[CoinWebsites]?
let twitter:[CoinTwitters]?
let facebook:[CoinFacebook]?
let explorer:[CoinExplorer]?
let reddit:[CoinReddits]?
}
struct CoinWebsites:Codable {
let website:String?
}
struct CoinTwitters:Codable {
let urlTwitters:String?
}
struct CoinFacebook:Codable {
let urlFacebook:String?
}
struct CoinExplorer:Codable {
let urlExplorer:String?
}
struct CoinReddits:Codable {
let urlEReddits:String?
}
json format:
{
"status":{
"timestamp":"2022-10-09T11:11:11.686Z",
"error_code":0,
"error_message":null,
"elapsed":1,
"credit_count":1,
"notice":null
},
"data":{
"1":{
"urls":{
"website":[
"pthkfb543fm",
"49xjybh5mlq",
"0uux1lvt44id",
"kqb4lyfeos",
"rbh8ui7r9dj",
"0em815h34ay9",
"zhmg6phhpmd",
"z6smii44j5",
"59bf5ofx2h4",
"95l4hn2qvr6"
],
"technical_doc":[
"oid34tehsbb",
"d1ofa6b2hbg",
"9l1xpu1bo7",
"ped2a98gup",
"y951pv6v55e",
"9tqxaa6capo",
"hssug4slmc6",
"28ocf6dnc3i",
"cddlngcaboe",
"xka0x1dijb"
],
"twitter":[
],
"reddit":[
"sbv1ndmtcb",
"wlu5zd1d2jq",
"o2b8f0xek3",
"70l3icwp1sd",
"pmcm26nvg7d",
"xz4idaq8at",
"utaqexwga6",
"px7o0o4e2f",
"ginsnepn93i",
"mqfaedmq29"
],
"message_board":[
"umt9tn7giq",
"n37dd8jqkq",
"b8j4r5gdoio",
"9hsoy1y579b",
"twexsn7t5di",
"v52nrhmnrc",
"jy5hui32j8k",
"sssb806c71m",
"t8sm0f2i1t",
"tm5osp7fstg"
],
"announcement":[
],
"chat":[
],
"explorer":[
"opde5rdke6",
"r6qhe54rmpl",
"eoj3z1xqssm",
"i09e7oxtj1b",
"rfah6o4912n",
"jrju212ljoo",
"oeyzlewitpi",
"o8l7lk1tsiq",
"iwms7fi859p",
"er098njihii"
],
"source_code":[
"grkckgsnlxd",
"nl208dwuitg",
"f09za84abdw",
"dq5319hlyag",
"ycf03rrymip",
"tf76bcn0w9f",
"2e0vl41amhw",
"ztpq27uwj3m",
"l3j3x6hnx5k",
"zj1c4cl13j"
]
},
"logo":"d0ln7k9juc",
"id":1,
"name":"blntl59cjh",
"symbol":"iaeaxzvx5jd",
"slug":"1y0k474cv1d",
"description":"i72hjlt621l",
"date_added":"2022-10-09T11:11:11.686Z",
"date_launched":"2022-10-09T11:11:11.686Z",
"tags":[
"n2jbg87vff",
"vr7mthp6s7",
"0vbnftw8hqz",
"h2vhpc39dwf",
"ocdozsqcv3",
"0sry86fib7k9",
"nqkgqwmhon",
"a6hlvwuv7o",
"n37q9hsx66a",
"8edmkawhdlq"
],
"platform":null,
"category":"w4w9ris8y9p"
},
"2":{
"urls":{
"website":[
"3fnvimztsqo",
"obpgb3o03qc",
"3rzbwjniljp",
"lwzp3g0l7qn",
"pj9i9esmycd",
"rxxqdzsh74h",
"c3h167i3gn9",
"nhztuwzrbqo",
"lu7gi5qm4fq",
"pmxizdq4j1"
],
"technical_doc":[
"ucnmd1rwgji",
"zxqw8ajty5",
"tihr9s3f69",
"l3ba21297z",
"54kuohb05xn",
"ml74ors5ltc",
"utnqamn2ud9",
"4wg8lcx8pbr",
"abhp5ohx12b",
"4fc1smpj5ps"
],
"twitter":[
],
"reddit":[
"alimp4er63t",
"urpga0uwill",
"dl68fd2bq8f",
"vp8mgbjcbv",
"w6p16dbnv5s",
"q8dvzg90d",
"1dkfx8g4f1ui",
"oederkt3df",
"00d49eblt6j3l",
"ywcnpmio49s"
],
"message_board":[
"cqoizsyx8mn",
"vqxjb3g2y2r",
"9oadavn71xm",
"ew9qubh8x4n",
"czbbkpt4egu",
"jbx26vqega",
"kynzrmrazae",
"s5twwsy7bw",
"rw7oep10pj",
"xqoyj0kc79q"
],
"announcement":[
],
"chat":[
],
"explorer":[
"ioac8iuqyma",
"v9xm5fpid7",
"hssvwnwhe17",
"9o77col8hk4",
"b6tr44woibq",
"3zoyuxe9s2z",
"eeh948ksf9o",
"qdhnncab0po",
"z80tc2ztsh",
"xki8g0zw8vh"
],
"source_code":[
"q5njdmu1tvp",
"rswxz9717k",
"fchf720dx3",
"rzzfhi5mk3g",
"t3qzejl5gt",
"qm22rerkrc",
"11lgg2etg4l",
"0dru9zhnof7",
"l2x2n8ueq0c",
"z33p76whb7c"
]
},
"logo":"jywrmmc68g",
"id":2,
"name":"uiyzzwog9d",
"symbol":"gy73ckf5l1v",
"slug":"ki7li2ah6l",
"description":"o7v6hhf1qce",
"date_added":"2022-10-09T11:11:11.686Z",
"date_launched":"2022-10-09T11:11:11.686Z",
"tags":[
"157427ygz4v",
"u5iba7d9yt",
"89xtswitklk",
"l8mwl50329c",
"av0ty13yxi8",
"27luj3irtrj",
"6bqwzp1w7lr",
"7zusdyi69od",
"kwxa2knt0dn",
"hpsc19nhm67"
],
"platform":null,
"category":"1jrjafok03s"
}
}
}
CodePudding user response:
I would appreciate an explanation of what the problem is and where I am wrong.
The problem is that the website, twitter, facebook, explorer, reddit keys are arrays of strings in the JSON response not arrays of custom objects so if you change the UrlsCoins to:
struct UrlsCoins:Codable {
let website:[String]?
let twitter:[String]?
let facebook:[String]?
let explorer:[String]?
let reddit:[String]?
}
You will be able to parse the JSON
CodePudding user response:
The problem you have is that the models you have do not match the json data you get from the server.
Try these structs models, mostly obtained from app.quicktype.io , and use them like as shown, to decode the server response (works well for me).
By inspection, you can find the differences between your models and "my" models that can decode the json data.
let results = try JSONDecoder().decode(InfoResponse.self, from: data)
// MARK: - InfoResponse
struct InfoResponse: Codable {
let status: Status
let data: [String: Datum]
}
// MARK: - Datum
struct Datum: Codable {
let urls: Urls
let logo: String
let id: Int
let name, symbol, slug, datumDescription: String
let dateAdded, dateLaunched: String
let tags: [String]
let platform: String?
let category: String
enum CodingKeys: String, CodingKey {
case urls, logo, id, name, symbol, slug
case datumDescription = "description"
case dateAdded = "date_added"
case dateLaunched = "date_launched"
case tags, platform, category
}
}
// MARK: - Urls
struct Urls: Codable {
let website, technicalDoc: [String]
let twitter: [String]
let reddit, messageBoard: [String]
let announcement, chat: [String]
let explorer, sourceCode: [String]
enum CodingKeys: String, CodingKey {
case website
case technicalDoc = "technical_doc"
case twitter, reddit
case messageBoard = "message_board"
case announcement, chat, explorer
case sourceCode = "source_code"
}
}
// MARK: - Status
struct Status: Codable {
let timestamp: String
let errorCode: Int
let errorMessage: String?
let elapsed, creditCount: Int
let notice: String?
enum CodingKeys: String, CodingKey {
case timestamp
case errorCode = "error_code"
case errorMessage = "error_message"
case elapsed
case creditCount = "credit_count"
case notice
}
}
You will have to check the docs, to determine which properties are optional. In that case add a ?
to it.