I have to decode an array of the dictionary, where the key is an enum & value is a model object.
Here is my sample JSON,
[
{
"nanomp4": {
"url": "https://media.tenor.com/videos/a1da4dcf693c2187615721d866decf00/mp4",
"dims": [
150,
138
],
"duration": 2.0,
"preview": "https://media.tenor.com/images/17d523e6b7c3c9a4ca64566a1890d94d/tenor.png",
"size": 70381
},
"nanowebm": {
"url": "https://media.tenor.com/videos/aa983425114e32ab446f669d91611938/webm",
"dims": [
150,
138
],
"preview": "https://media.tenor.com/images/17d523e6b7c3c9a4ca64566a1890d94d/tenor.png",
"size": 53888
},
},
{
"nanomp4": {
"url": "https://media.tenor.com/videos/a1da4dcf693c2187615721d866decf00/mp4",
"dims": [
150,
138
],
"duration": 2.0,
"preview": "https://media.tenor.com/images/17d523e6b7c3c9a4ca64566a1890d94d/tenor.png",
"size": 70381
},
}
]
Here is my decoding code,
do {
let data = try Data(contentsOf: fileURL)
let decoder = JSONDecoder()
let collection = try decoder.decode([[GIFFormat:Media]].self, from: data)
print(collection)
} catch {
print("Error in parsing/decoding JSON: \(error)")
}
Here GIFFormat
is Enum & Media
is the model object, and they are decoding perfectly fine.
enum GIFFormat: String, Decodable {
case nanoMP4 = "nanomp4"
case nanoWebM = "nanowebm"
}
struct Media: Decodable {
let url: URL?
let dims: [Int]?
let duration: Double?
let preview: URL?
let size: Int64?
}
My console prints,
typeMismatch(Swift.Array<Any>, Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "Expected to decode Array<Any> but found a dictionary instead.", underlyingError: nil))
Can anyone explain to me what is exactly wrong here?
Even though the rawValue
for GIFFormat
is String
, GIFFormat
itself is an enum. You should update
let collection = try decoder.decode([[GIFFormat:Media]].self, from: data)
to
let collection = try decoder.decode([[GIFFormat.RawValue:Media]].self, from: data)
UPDATE: In response to your comment
Now to access value, I need to use like this,
collection?.first?[GIFFormat.mp4.rawValue]?.url
. Which is again ugly !!
I would suggest a bit of refactoring. You can start by removing your enum
altogether. Keep your Media
struct. Create a new Collection
struct
struct Collection: Decodable {
let nanomp4: Media!
let nanowebm: Media!
}
Then, you can update the above line to
let collection = try decoder.decode([Collection].self, from: data)
and your ugly line transforms into
collection.first?.nanomp4.url
NOTE: This solution assumes that you only have nanomp4
& nanowebm
as your enum values. If this is not the case, then this might not be the best solution and you might have to go with the first solution.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.