Why my structs doesn't conform to Encodable and Decodable?

85 Views Asked by At

Here are my structs for decoding JSON files. Xcode gives errors and says they don't conform Encodable and Decodable. This one:

struct SocialModel: Codable {
    let id: Int
    let likeCount: Int
    let commentCounts: CommentCounts
    
    enum CodingKeys: String, CodingKey {
        case id
        case likeCount
        case commentCounts
    }
    
    init(id: Int, likeCount: Int, commentCounts: CommentCounts) {
        self.id = id
        self.likeCount = likeCount
        self.commentCounts = commentCounts
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        id = try container.decodeIfPresent(Int.self, forKey: .id) ?? 123
        likeCount = try container.decode(Int.self, forKey: .likeCount)
        commentCounts = try container.decode(CommentCounts.self, forKey: .commentCounts)
    }
}

struct CommentCounts: Codable {
    let averageRating, anonymousCommentsCount, memberCommentsCount: Int
}

and this one:

struct ProductModel: Codable {
    let productId: Int
    let name, desc: String
    let productImage: String
    let productPrice: Price
}

struct Price: Codable {
    let value: Int
    let currency: String
}

Anyone can tell me why? I tried to build them many times, but it didn't work at the end.

1

There are 1 best solutions below

1
On BEST ANSWER

Your structs don't conform to the Encodable and Decodable protocols because you have implemented custom initializers, which may conflict with the default coding mechanisms provided by Swift for Codable conformance. To make your structs conform to Codable, you should implement the init(from:) and encode(to:) methods to specify how your custom types should be encoded and decoded.

Here's an updated version of your structs with the necessary init(from:) and encode(to:) methods:

struct SocialModel: Codable {
    let id: Int
    let likeCount: Int
    let commentCounts: CommentCounts

    enum CodingKeys: String, CodingKey {
        case id
        case likeCount
        case commentCounts
    }

    init(id: Int, likeCount: Int, commentCounts: CommentCounts) {
        self.id = id
        self.likeCount = likeCount
        self.commentCounts = commentCounts
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        id = try container.decode(Int.self, forKey: .id)
        likeCount = try container.decode(Int.self, forKey: .likeCount)
        commentCounts = try container.decode(CommentCounts.self, forKey: .commentCounts)
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(id, forKey: .id)
        try container.encode(likeCount, forKey: .likeCount)
        try container.encode(commentCounts, forKey: .commentCounts)
    }
}

struct CommentCounts: Codable {
    let averageRating, anonymousCommentsCount, memberCommentsCount: Int
}

struct ProductModel: Codable {
    let productId: Int
    let name, desc: String
    let productImage: String
    let productPrice: Price
}

struct Price: Codable {
    let value: Int
    let currency: String
}

By implementing the encode(to:) method in the SocialModel struct, you provide instructions on how to encode your custom types, making your structs conform to the Encodable protocol. Similarly, the init(from:) method in the SocialModel struct specifies how to decode your custom types, making your structs conform to the Decodable protocol.