简体   繁体   English

使用Swift中的子类可解码

[英]Decodable with subclasses in Swift

I'm new with Decodable in swift. 我是迅速了解Decodable的新手。 I just learned how to use it but I'm stuck with trying to decode a subclass within another class's init(from decoder: ). 我刚刚学习了如何使用它,但是我一直试图在另一个类的init中解码一个子类(来自解码器:)。

The question is how do I decode this other class from the original class init? 问题是如何从原始类init解码另一个类?

I get a user JSON file looking like this 我得到一个用户JSON文件,看起来像这样

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

I have a User class that looks like this 我有一个看起来像这样的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???

   }

   ...

}

I also have a SocialNetwork class. 我也有一个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) ?? ""
   }

   ...

}

You don't have to write any custom init 您不必编写任何自定义init

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
}

For a try it would be 尝试一下

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

But the decoder do this for you 但是解码器可以帮你

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM