/ / Властивість власного класу Codable не може ініціалізувати власні властивості з JSON - json, swift, swift4, codable, custom-properties

Властивість типу власного класу Codable не може ініціалізувати власні властивості з JSON - json, swift, swift4, codable, custom-властивості

Мій 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
}
]
}

Мій Codable Модельні класи

Статті. 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)
}

}

Проблема:

Я намагаюся використати Codable протокол для ініціалізації моїх класів моделі з JSON.Це добре працює для власних типів даних (String, Int тощо), але якщо структура містить об'єкт властивості власного типу, це не ініціалізує властивості цієї спеціальної структури (класу).

Приклад: Category є об'єктом нетипового типу в Article структура. Кожен спеціальний клас відповідає за ініціалізацію його властивостей, підтверджує Codable протокол і має свій власний init(from decoder: Decoder) метод

Але якось category та інші користувальницькі типи не можуть ініціалізувати власні властивості (наприклад category_name = nil в Category клас, і те саме відбувається з Parent_category і Main_image_urls), і я отримую такий результат: (Деякі значення дорівнюють нулю)

Журнал консолі на 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

Мені чогось не вистачає? Будь ласка, допоможіть хлопцям :-)

Відповіді:

2 для відповіді № 1

В Article.swift спробуйте змінити наступні рядки

category = try Category(from: decoder)
main_image_urls = try Main_image_urls(from: decoder)

до

category = values.decodeIfPresent(Category.self, forKey: .category)
main_image_urls = values.decodeIfPresent(Main_image_urls.self, forKey: .main_image_urls)

Ваш клас Main_image_urls також повинен відповідати кодуванню.

Ви також можете спробувати опустити init(from decoder: Decoder) методів і нехай компілятор синтезує його. Це також працює, коли є власний перелік CodingKeys.

Оновлення:

Також змініть наступний рядок у Category.swift

parent_category = try Parent_category(from: decoder)

до

parent_category = values.decodeIfPresent(Parent_category.self, forKey: .parentCategory)