Декодируемый с подклассами в Swift - PullRequest
1 голос
/ 12 марта 2019

Я новичок в Decodable в Swift.Я только что узнал, как его использовать, но я застрял при попытке декодировать подкласс внутри init другого класса (из decoder:).

Вопрос в том, как мне декодировать этот другой класс из исходного класса init?

Я получаю пользовательский JSON-файл, похожий на этот

{
     firstName:Tim,
     LastName: Apple,
     ...
     socialNetworks: [
         {
             name: Facebook,
             username: Tim85,
             ...
         },
         {
             name: Twitter,
             username: Tim_85,
             ...
         },
         ...
     ],
 }

У меня есть класс User, который выглядит следующим образом

class User: Codable {

   firstName: String,
   lastName: String,
   ...
   socialNetworks: [SocialNetwork]


   enum CodingKeys: String, CodingKey {
       case firstName, lastName, ..., socialNetworks
   }

   required init(from decoder: Decoder) throws {
       let container = try decoder.container(keyedBy: CodingKeys.self)

       self.firstName = try container.decodeIfPresent(String.self, forKey: .firstName) ?? ""
       self.lastName = try container.decodeIfPresent(String.self, forKey: .lastName) ?? ""

       // How do I also decode SocialNetworks???

   }

   ...

}

У меня также есть класс SocialNetwork.

class SocialNetwork: Codable {

   name: String,
   username: String,
   ...


   enum CodingKeys: String, CodingKey {
       case name, username, ...
   }

   required init(from decoder: Decoder) throws {
       let container = try decoder.container(keyedBy: CodingKeys.self)

       self.name = try container.decodeIfPresent(String.self, forKey: .name) ?? ""
       self.username = try container.decodeIfPresent(String.self, forKey: .userName) ?? ""
   }

   ...

}

1 Ответ

2 голосов
/ 12 марта 2019

Вам не нужно писать какую-либо пользовательскую инициацию

struct Root: Codable {
    let firstName, lastName: String
    let socialNetworks: [SocialNetwork]

    enum CodingKeys: String, CodingKey { // you can remove this block if LastName starts with l small instead of L
        case firstName
        case lastName = "LastName"
        case socialNetworks
    }
}

struct SocialNetwork: Codable {
    let name, username: String
}

Для попытки это будет

self.socialNetworks = try container.decodeIfPresent([SocialNetwork].self, forKey: .socialNetworks) ?? []

Но декодер сделает это за вас

...