5

I am having issues gracefully handling this error debugDescription: "Expected String value but found null instead." I understand that in my struct that conforms to Codable, my stored property would need to be declared an optional string, as I read in this post

I tried that and still the error occurs. I read also in that post that I could also customize the decoder to replace nil with an empty string. I do not know how to achieve this honestly.

here is my code:

struct Discover: Codable {
    var page: Int
    var totalResults: Int
    var totalPages: Int
    var results: [DiscoverResults]

     enum CodingKeys: String, CodingKey {
        case page
        case totalResults = "total_results"
        case totalPages = "total_pages"
        case results = "results"
    }

}

struct DiscoverResults {
    var title: String
    var releaseDate: String
    var posterPath: String?
    var id: Int
    var genreIds: [Int]
    var poster: UIImage?

     enum CodingKeys: String, CodingKey {
        case title
        case posterPath = "poster_path"
        case releaseDate = "release_date"
        case id
        case genreIds = "genre_ids"
    }
}

extension DiscoverResults: Decodable {
    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        title = try values.decode(String.self, forKey: .title)
        releaseDate = try values.decode(String.self, forKey: .releaseDate)
        posterPath = try values.decode(String.self, forKey: .posterPath)
        id = try values.decode(Int.self, forKey: .id)
        genreIds = try values.decode([Int].self, forKey: .genreIds)
    }
}

extension DiscoverResults: Encodable {
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(title, forKey: .title)
        try container.encode(posterPath, forKey: .posterPath)
        try container.encode(releaseDate, forKey: .releaseDate)
        try container.encode(id, forKey: .id)
        try container.encode(genreIds, forKey: .genreIds)
    }
}

The posterPath in DiscoverResults is null for some of the movies as I am using a movie api. If the JSON itself is needed I will edit the post.

Kevin
  • 53,822
  • 15
  • 101
  • 132
Max
  • 173
  • 2
  • 8
  • 3
    Try the duplicate (use `decodeIfPresent` rather than `decode`), if it doesn't work you'll need to post the JSON. – Kevin Jan 08 '18 at 19:25
  • @Kevin that posted worked like a charm. Learn something new everyday! I appreciate the quick help. – Max Jan 08 '18 at 19:33
  • 1
    You should just be able to use the auto compiler-generated `Decodable` conformance, which uses `decodeIfPresent` for optionals. Note that there's currently a bug where you have to say `var poster: UIImage? = nil` for it to synthesise. Also, if you're okay with using `encodeIfPresent` for optional properties, you can use the compiler-generated `Encodable` conformance too. – Hamish Jan 08 '18 at 19:33
  • I was having the same issue fixed it using `let container = try decoder.container(keyedBy: CodingKeys.self) try container.decodeIfPresent(String.self, forKey: .posterPath)` – Badrinath Nov 14 '18 at 23:11

0 Answers0