0
votes

I'm having hard time decoding with swift Decodable protocol. I have a REST API which returns the following JSON

{
  data: [
    {
      id: 17,
      status: "published",
      created_by: {
        id: 1
      },
      created_on: "2020-01-13 17:38:31",
      title: "Lorem ipsum dolor sit amet, consectetur adi",
      content: "<p>Mauris id ligula et metus porta rutrum vitae ac mi. Mauris rhoncus sagittis facilisis. Cras suscipit nisi quis risus lacinia dictum. Morbi porttitor, est sodales tristique interdum, erat leo consequat lorem, in cursus metus est eget felis. Cras a sapien massa. Sed tincidunt fermentum imperdiet. Ut velit diam, interdum sit amet lectus vitae, tristiq</p>",
      featured_image: {
        data: {
          full_url: "https://example.com/originals/14eefd0d-93fc-44f6-84a5-7cf86a2e83fc.jpg",
          url: "/uploads/abc/originals/14eefd0d-93fc-44f6-84a5-7cf86a2e83fc.jpg",
          thumbnails: [...],
          embed: null
        }
      },
      source: null,
      is_featured: true
    }
  ]
}

And the structure of my model

struct PostRoot:Decodable {
    let data:[Post]
}

struct Post: Decodable {
    let id:Int
    let title:String
    let created_on:String
    let content:String
    let source:String
    let f_image:FeaturedImage
}

struct FeaturedImage: Decodable {
    let data:ImagePath
}

struct ImagePath: Decodable{
    let full_url:String
}

// Only included the decoding part, not the request part

if let d = data {
  let decodedLists = try JSONDecoder().decode(PostRoot.self, from: d)
  print(decodedLists)
}

After getting the response from my server, the decoding process always ends up in error, do I have to map each and every keys ? what am I missing here ?

This is the error:

Error: keyNotFound(CodingKeys(stringValue: "f_image", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "No value associated with key CodingKeys(stringValue: \"f_image\", intValue: nil) (\"f_image\").", underlyingError: nil))

1
Please share the error. - koen
Also, that is not valid JSON (you can check the for instance here: jsonlint.com). - koen
Surround your decoding with a do/catch and print the error in the catch so you can include it in your question . Some pointers though, source is optional and there is no json key matching f_image - Joakim Danielson
Your JSON has featured_image, but your model has f_image. They need to be the same. - koen
source is null, it should be optional in the model, you need to change the type to String? - Adam

1 Answers

0
votes

Maybe this could help, it was autogenerate by "Paste JSON as Code", it seams that some of the keys in your code are missing. Also a possible error could be that that is not JSON, the keys are not strings and so cannot be decoded like that.

// MARK: - PostRoot
struct PostRoot: Codable {
    let data: [Post]
}

// MARK: - Post
struct Post: Codable {
    let id: Int
    let status: String
    let createdBy: CreatedBy
    let createdOn, title, content: String
    let featuredImage: FeaturedImage
    let source: String?
    let isFeatured: Bool

    enum CodingKeys: String, CodingKey {
        case id, status
        case createdBy = "created_by"
        case createdOn = "created_on"
        case title, content
        case featuredImage = "featured_image"
        case source
        case isFeatured = "is_featured"
    }
}

// MARK: - CreatedBy
struct CreatedBy: Codable {
    let id: Int
}

// MARK: - FeaturedImage
struct FeaturedImage: Codable {
    let data: DataClass
}

// MARK: - DataClass
struct DataClass: Codable {
    let fullURL: String
    let url: String
    let thumbnails: [String]
    let embed: String?

    enum CodingKeys: String, CodingKey {
        case fullURL = "full_url"
        case url, thumbnails, embed
    }
}