Reputation: 1002
What is the data model corresponding to the below json?
{
dog:
{
type: "dog",
logoLocation: "url1"
},
pitbull:
{
type: "pitbull",
logoLocation: "url2"
}
}
This is a dictionary of dictionaries So I tried,
class PhotosCollectionModel: Codable {
var photoDictionary: Dictionary<String, PhotoModel>?
}
class PhotoModel: Codable {
var type: String?
var logoLocation: String?
}
But it is not working. Any help please?
Upvotes: 1
Views: 2169
Reputation: 923
Use the below struct for unwrapping the data
// MARK: - Response
struct Response: Codable {
let dog, pitbull: Dog?
enum CodingKeys:String, CodingKey {
case dog
case pitbull
}
init(from decoder: any Decoder) throws {
let container = try? decoder.container(keyedBy: CodingKeys.self)
dog = try? container?.decodeIfPresent(Dog.self, forKey: .dog)
pitbull = try? container?.decodeIfPresent(Dog.self, forKey: .pitbull)
}
}
// MARK: - Dog
struct Dog: Codable {
let type, logoLocation: String?
enum CodingKeys:String, CodingKey {
case type
case logoLocation
}
init(from decoder: any Decoder) throws {
let container = try? decoder.container(keyedBy: CodingKeys.self)
type = try? container?.decodeIfPresent(String.self, forKey: .type)
logoLocation = try? container?.decodeIfPresent(String.self, forKey: .logoLocation)
}
}
Use the below code for decode the json Data
do {
let dictonary = try JSONDecoder().decode([String:Dog].self,from:data)
// Or use this code
let response = try JSONDecoder().decode(Response.self,from:data)
}
catch let error{
print(error)
}
Upvotes: 0
Reputation: 51882
I would skip the first class and keep
struct PhotoModel: Codable {
let type: String
let logoLocation: String
}
and then decode it like a dictionary
do {
let decoder = JSONDecoder()
let result = try decoder.decode([String: PhotoModel].self, from: data)
result.forEach { (key,value) in
print("Type: \(value.type), logo: \(value.logoLocation) (key: \(key))")
}
} catch {
print(error)
}
Outputs
Type: dog, logo: url1 (key: dog)
Type: pitbull, logo: url2 (key: pitbull)
Are really both attributes optional, if not I suggest you remove any unnecessary ?
in PhotoModel
(I did)
Upvotes: 0
Reputation: 100503
You need
struct Root: Codable {
let dog, pitbull: Dog
}
struct Dog: Codable {
let type, logoLocation: String // or let logoLocation:URL
}
Correct json
{
"dog":
{
"type": "dog",
"logoLocation": "url1"
},
"pitbull":
{
"type": "pitbull",
"logoLocation": "url2"
}
}
for dynamic
just use [String:Dog]
in Decoder
do {
let res = try JSONDecoder().decode([String:Dog].self,from:data)
}
catch {
print(error)
}
Upvotes: 3