Как использовать Decodable Protocol для создания общего класса для одинаковых свойств Json с разными ключами
{
"actions" : {
"upvote" : {
"delete" : true,
"read" : true,
"create" : true,
"update": true
},
"read" : {
"delete" : true,
"update" : true,
"read" : true,
"create" : true
}
}
}
У меня есть этот ответ Json, поступающий с сервера, и ниже приведены структурные модели, созданные с использованием декодируемого протокола.
struct Actions: Decodable {
let upvote: UpvoteStatus
let read: ReadStatus
enum CodingKeys: String, CodingKey {
case upvote
case read
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.upvote = try container.decode(UpvoteStatus.self, forKey: .upvote) {
self.read = try container.decode(ReadStatus.self, forKey: .read)
}
}
struct UpvoteStatus: Decodable {
let delete: Bool
let update: Bool
let read: Bool
let create: Bool
}
struct ReadStatus: Decodable {
var delete: Bool
var update: Bool
var read: Bool
var create: Bool
}
Это прекрасно работает, но создает много дублирующегося кода, поскольку структуры UpvoteStatus и ReadStatus имеют схожие свойства, а JSON с сервера аналогичен, за исключением разных ключей.
Можно ли каким-либо образом создать общую структуру статуса, добавить свойство статуса в классы ReadStatus и UpvoteStatus?
struct Status: Decodable {
let delete: Bool
let update: Bool
let read: Bool
let create: Bool
}
Теперь я хочу иметь что-то вроде ниже, чтобы я мог удалить дубликат кода.
struct UpvoteStatus: Decodable {
let status: Status
}
struct ReadStatus: Decodable {
let status: Status
}
2 ответа
Решение
Возможно, это то, что вам нужно, может быть, вы слишком усердно об этом думаете:
struct Actions: Decodable {
let upvote: Status
let read: Status
enum CodingKeys: String, CodingKey {
case upvote
case read
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.upvote = try container.decode(Status.self, forKey: .upvote) {
self.read = try container.decode(Status.self, forKey: .read)
}
}
struct Status: Decodable {
let delete: Bool
let update: Bool
let read: Bool
let create: Bool
}
Нет необходимости писать собственный инициализатор и явно определять ключи кодирования.
Вы можете просто написать
struct Response: Codable {
let actions: Actions
struct Actions : Codable {
let upvote: Element
let read: Element
struct Element: Codable {
let delete: Bool
let read: Bool
let create: Bool
let update: Bool
}
}
}