My Json:
{
"message":"OK",
"response":[
{
"article_id":"201802062200722818",
"lead":"Poliisi vapautti naisen ja otti miehen kiinni. Satakunnan käräjäoikeus vangitsi miehen tiistaina.",
"headline":"Poliisi epäilee: 19-vuotias raumalaismies piti alaikäistä naista mökillä vankina",
"title":"Poliisi epäilee: 19-vuotias raumalaismies piti alaikäistä naista mökillä vankina",
"service_name":"iltalehti",
"main_image_name":"cae51c694cc7f31257290ff96489f3cf852329a887509621b29a27fbaa0f8894.jpg",
"category":{
"category_name":"kotimaa",
"description":"Kotimaan uutiset",
"parent_category":{
"category_name":"uutiset",
"description":"Uutiset",
"parent_category":null
}
},
"main_image_urls":{
"default":"https://img.ilcdn.fi/PcWFp0weItXN2WAWKBXCO_H2VsQ=/510x/img-s3.ilcdn.fi/cae51c694cc7f31257290ff96489f3cf852329a887509621b29a27fbaa0f8894.jpg",
"size30":"https://img.ilcdn.fi/_LNHr84u93ntg3tX37oHyGBlRNA=/30x/img-s3.ilcdn.fi/cae51c694cc7f31257290ff96489f3cf852329a887509621b29a27fbaa0f8894.jpg",
"size98":"https://img.ilcdn.fi/r624bQFqaJ3xqrMScif38JH6SBM=/98x/img-s3.ilcdn.fi/cae51c694cc7f31257290ff96489f3cf852329a887509621b29a27fbaa0f8894.jpg",
"size138":"https://img.ilcdn.fi/dyemZCdMpjAFTnnD5JiYLh3WGJI=/138x/img-s3.ilcdn.fi/cae51c694cc7f31257290ff96489f3cf852329a887509621b29a27fbaa0f8894.jpg",
"size244":"https://img.ilcdn.fi/2AiJpLa4oLxEDE0jL_LazhOiTMM=/244x/img-s3.ilcdn.fi/cae51c694cc7f31257290ff96489f3cf852329a887509621b29a27fbaa0f8894.jpg",
"size293":"https://img.ilcdn.fi/iyAZVQ0ufAHrX2inGCiE9QPQjMU=/293x/img-s3.ilcdn.fi/cae51c694cc7f31257290ff96489f3cf852329a887509621b29a27fbaa0f8894.jpg",
"size310":"https://img.ilcdn.fi/XGmL7EEqo0OR5Vzvbel1hSeTmHI=/310x/img-s3.ilcdn.fi/cae51c694cc7f31257290ff96489f3cf852329a887509621b29a27fbaa0f8894.jpg",
"size510":"https://img.ilcdn.fi/PcWFp0weItXN2WAWKBXCO_H2VsQ=/510x/img-s3.ilcdn.fi/cae51c694cc7f31257290ff96489f3cf852329a887509621b29a27fbaa0f8894.jpg",
"size820":"https://img.ilcdn.fi/N-XV5ZqQASGpvUe-3DAcq4i1928=/820x/img-s3.ilcdn.fi/cae51c694cc7f31257290ff96489f3cf852329a887509621b29a27fbaa0f8894.jpg",
"size1024":"https://img.ilcdn.fi/J5Cm5P2SJMNymHza7s3LdEEvKLg=/1024x/img-s3.ilcdn.fi/cae51c694cc7f31257290ff96489f3cf852329a887509621b29a27fbaa0f8894.jpg"
},
"published_at":"2018-02-06T10:42:40+02:00",
"updated_at":null
}
]
}
My Codable
Model classes
Articles.swift
import Foundation
struct Articles : Codable {
let message : String?
let response : [Article]?
enum CodingKeys: String, CodingKey {
case message = "message"
case response = "response"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
message = try values.decodeIfPresent(String.self, forKey: .message)
response = try values.decodeIfPresent([Article].self, forKey: .response)
}
}
Article.swift
import Foundation
struct Article : Codable {
let article_id : String?
let lead : String?
let headline : String?
let title : String?
let service_name : String?
let main_image_name : String?
let category : Category?
let main_image_urls : Main_image_urls?
let published_at : String?
let updated_at : String?
enum CodingKeys: String, CodingKey {
case article_id = "article_id"
case lead = "lead"
case headline = "headline"
case title = "title"
case service_name = "service_name"
case main_image_name = "main_image_name"
case category
case main_image_urls
case published_at = "published_at"
case updated_at = "updated_at"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
article_id = try values.decodeIfPresent(String.self, forKey: .article_id)
lead = try values.decodeIfPresent(String.self, forKey: .lead)
headline = try values.decodeIfPresent(String.self, forKey: .headline)
title = try values.decodeIfPresent(String.self, forKey: .title)
service_name = try values.decodeIfPresent(String.self, forKey: .service_name)
main_image_name = try values.decodeIfPresent(String.self, forKey: .main_image_name)
category = try Category(from: decoder)
main_image_urls = try Main_image_urls(from: decoder)
published_at = try values.decodeIfPresent(String.self, forKey: .published_at)
updated_at = try values.decodeIfPresent(String.self, forKey: .updated_at)
}
}
Category.swift
import Foundation
struct Category : Codable {
let category_name : String?
let description : String?
let parent_category : Parent_category?
enum CodingKeys: String, CodingKey {
case category_name = "category_name"
case description = "description"
case parent_category
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
category_name = try values.decodeIfPresent(String.self, forKey: .category_name)
description = try values.decodeIfPresent(String.self, forKey: .description)
parent_category = try Parent_category(from: decoder)
}
}
Parent_category.swift
import Foundation
struct Parent_category : Codable {
let category_name : String?
let description : String?
let parent_category : String?
enum CodingKeys: String, CodingKey {
case category_name = "category_name"
case description = "description"
case parent_category = "parent_category"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
category_name = try values.decodeIfPresent(String.self, forKey: .category_name)
description = try values.decodeIfPresent(String.self, forKey: .description)
parent_category = try values.decodeIfPresent(String.self, forKey: .parent_category)
}
}
Problem:
I am trying to use Codable
protocol to initialize my model classes from JSON. It works well for native datatypes (String, Int etc.), But If structure contains custom type property object, it is not initializing the properties of that custom structure (class).
Example: Category
is custom type object in Article
struct. Every custom class is responsible to initialize its properties, confirms Codable
protocol and has its own init(from decoder: Decoder)
method.
But somehow category
and other custom types are not able to initialize their own properties.(e.g category_name = nil
in Category
class, and same is happening with Parent_category
and Main_image_urls
) and I am getting following result: (Some values are nil)
Console log on xcode
po article
▿ Optional<Article>
▿ some : Article
▿ article_id : Optional<String>
- some : "201802062200722818"
▿ lead : Optional<String>
- some : "Poliisi vapautti naisen ja otti miehen kiinni. Satakunnan käräjäoikeus vangitsi miehen tiistaina."
▿ headline : Optional<String>
- some : "Poliisi epäilee: 19-vuotias raumalaismies piti alaikäistä naista mökillä vankina"
▿ title : Optional<String>
- some : "Poliisi epäilee: 19-vuotias raumalaismies piti alaikäistä naista mökillä vankina"
▿ service_name : Optional<String>
- some : "iltalehti"
▿ main_image_name : Optional<String>
- some : "cae51c694cc7f31257290ff96489f3cf852329a887509621b29a27fbaa0f8894.jpg"
▿ category : Optional<Category>
▿ some : Category
- category_name : nil
- description : nil
▿ parent_category : Optional<Parent_category>
▿ some : Parent_category
- category_name : nil
- description : nil
- parent_category : nil
▿ main_image_urls : Optional<Main_image_urls>
▿ some : Main_image_urls
- default : nil
- size30 : nil
- size98 : nil
- size138 : nil
- size244 : nil
- size293 : nil
- size310 : nil
- size510 : nil
- size820 : nil
- size1024 : nil
▿ published_at : Optional<String>
- some : "2018-02-06T10:42:40+02:00"
- updated_at : nil
Am I missing something? Please help guys :-)
In Article.swift
try change the following lines
category = try Category(from: decoder)
main_image_urls = try Main_image_urls(from: decoder)
to
category = values.decodeIfPresent(Category.self, forKey: .category)
main_image_urls = values.decodeIfPresent(Main_image_urls.self, forKey: .main_image_urls)
Your class Main_image_urls
should also conform to codable.
You could also try to omit the init(from decoder: Decoder)
methods and let the compiler synthesize it. This also works when having a custom CodingKeys enum.
Update:
Also change the following line in Category.swift
parent_category = try Parent_category(from: decoder)
to
parent_category = values.decodeIfPresent(Parent_category.self, forKey: .parentCategory)