1

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?

2
  • 1
    What is not working in particular? Commented Feb 17, 2019 at 16:00
  • app.quicktype.io Commented Feb 18, 2019 at 4:16

3 Answers 3

3

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)
    }
Sign up to request clarification or add additional context in comments.

3 Comments

If there are n elements like dog, pitbull?
Giving it as array try JSONDecoder().decode([String:Dog].self,from:data) here works. But when i create a model and separately it doesn't work. May i know why?
the [] in [String:Dog] doesn't mean it's an array , the result is a dictionary , for Array [[String:Dog]] that won't decode with your current json structure
0

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)

5 Comments

@ArashEtemad I don't understand your comment, could you clarify?
.convertFromSnakeCase should be .convertFromCamelCase
@ArashEtemad First of all setting that property is not needed here, a copy & paste error if anything and secondly it should be .convertFromSnakeCase. and nothing else
I know this is not required but snakeCase is wrong here and it should be .useDefaultKeys in this answer, you sure you know difference between camel case and snake case?
@ArashEtemad there isn’t even such a thing as .convertFromCamelCase so give it a break. I did remove setting the property since it wasn’t relevant here in the first place
0

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)
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.