如何使用 Swift Decodable 从一组 UUID 键映射关系?
How to use Swift Decodable to map relationships from an array of UUID keys?
我有一个结构,其中:
Factories
有很多 Cards
;
而且,players
可以有多个Cards
(未实现);他们是同一张牌。
用于测试和内部完整性检查;我想暂时将卡片数组放在自己的 JSON 数组中。
所以我想出的结构是这样的:
// Example JSON
{
"factories": [
{
"id": "7a24a713-c0aa-4498-....",
"name": "Steel Factory",
"cost": 4,
"references": [
{ "id": "e936b897-c203-44a5-9cf0-27720f655b68" },
{ "id": "da35424a-6546-4c72-a51c-1f6abfd601a3" }
],
...
"cards": [
{ "id": "e936b897-c203-44a5-9cf0-27720f655b68", name: "Card #1", cost: 4 }
{ "id": "da35424a-6546-4c72-a51c-1f6abfd601a3", name: "Card #2", cost: 4 }
]
...
}
备注
The Factory JSON structure has no cards
; its considered to be an empty array when decoding
用例:
Fill the factories cards array (empty at init) with the contents of the references based off the matching UUID keys <
Swift 结构是:
struct Factory: Codable, Identifiable, Equatable, Hashable {
let id: UUID
let name: String
let cost: Int
var cards: [Card]?
internal var references: [Reference]?
private enum CodingKeys: String, CodingKey {
case id, name, cost, references
}
}
struct Reference: Codable, Identifiable, Hashable, Equatable {
var id: UUID
private enum CodingKeys: String, CodingKey {
case id
}
}
struct Card: Codable, Identifiable, Hashable, Equatable {
var id: UUID
var name: String
var cost: Int
private enum CodingKeys: String, CodingKey {
case id, name, cost
}
}
所以,尝试这样做;我已经为每个结构写出自定义 initWithCoder
。
extension Reference {
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(UUID.self, forKey: .id)
}
}
extension Factory {
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(UUID.self, forKey: .id)
name = try container.decode(String.self, forKey: .name)
cost = try container.decode(Int.self, forKey: .cost)
cards = try container.decodeIfPresent([Card].self, forKey: .cards) ?? [Card]()
references = try container.decode([Reference].self, forKey: .references)
}
}
extension Card {
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(UUID.self, forKey: .id)
name = try container.decode(String.self, forKey: .name)
cost = try container.decode(String.self, forKey: .cost)
}
}
我想做这样的事情:
// Factory decoder
references = try container.decode([Reference].self, forKey: .references)
// Find all cards that match the reference ID
// add the matched cards to this factories cards array
let matchedCards: [Card]? = references.map { [=14=] }
print ("matchedCards")
但考虑到无法通过此结构直接访问 Card 结构,我不确定将 $0 映射到什么。
我知道我可以将卡片作为子数组放在工厂结构中。
但我正在考虑,将来可能会出现一个桥接结构,其中包含关键引用,例如 one to many through
JSON 结构。
我感谢提供的任何反馈。
let referenceIds:[String] = references.map { [=10=].id }
let decodedCards = container.decode([Card].self, forKey: .cards)
let matchedCards[Card] = decodedCards.filter(where: { referenceIds.contains([=10=].id)})
self.cards = matchedCards // factory.cards
我有一个结构,其中:
Factories
有很多 Cards
;
而且,players
可以有多个Cards
(未实现);他们是同一张牌。
用于测试和内部完整性检查;我想暂时将卡片数组放在自己的 JSON 数组中。
所以我想出的结构是这样的:
// Example JSON
{
"factories": [
{
"id": "7a24a713-c0aa-4498-....",
"name": "Steel Factory",
"cost": 4,
"references": [
{ "id": "e936b897-c203-44a5-9cf0-27720f655b68" },
{ "id": "da35424a-6546-4c72-a51c-1f6abfd601a3" }
],
...
"cards": [
{ "id": "e936b897-c203-44a5-9cf0-27720f655b68", name: "Card #1", cost: 4 }
{ "id": "da35424a-6546-4c72-a51c-1f6abfd601a3", name: "Card #2", cost: 4 }
]
...
}
备注
The Factory JSON structure has no
cards
; its considered to be an empty array when decoding
用例:
Fill the factories cards array (empty at init) with the contents of the references based off the matching UUID keys <
Swift 结构是:
struct Factory: Codable, Identifiable, Equatable, Hashable {
let id: UUID
let name: String
let cost: Int
var cards: [Card]?
internal var references: [Reference]?
private enum CodingKeys: String, CodingKey {
case id, name, cost, references
}
}
struct Reference: Codable, Identifiable, Hashable, Equatable {
var id: UUID
private enum CodingKeys: String, CodingKey {
case id
}
}
struct Card: Codable, Identifiable, Hashable, Equatable {
var id: UUID
var name: String
var cost: Int
private enum CodingKeys: String, CodingKey {
case id, name, cost
}
}
所以,尝试这样做;我已经为每个结构写出自定义 initWithCoder
。
extension Reference {
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(UUID.self, forKey: .id)
}
}
extension Factory {
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(UUID.self, forKey: .id)
name = try container.decode(String.self, forKey: .name)
cost = try container.decode(Int.self, forKey: .cost)
cards = try container.decodeIfPresent([Card].self, forKey: .cards) ?? [Card]()
references = try container.decode([Reference].self, forKey: .references)
}
}
extension Card {
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(UUID.self, forKey: .id)
name = try container.decode(String.self, forKey: .name)
cost = try container.decode(String.self, forKey: .cost)
}
}
我想做这样的事情:
// Factory decoder
references = try container.decode([Reference].self, forKey: .references)
// Find all cards that match the reference ID
// add the matched cards to this factories cards array
let matchedCards: [Card]? = references.map { [=14=] }
print ("matchedCards")
但考虑到无法通过此结构直接访问 Card 结构,我不确定将 $0 映射到什么。
我知道我可以将卡片作为子数组放在工厂结构中。
但我正在考虑,将来可能会出现一个桥接结构,其中包含关键引用,例如 one to many through
JSON 结构。
我感谢提供的任何反馈。
let referenceIds:[String] = references.map { [=10=].id }
let decodedCards = container.decode([Card].self, forKey: .cards)
let matchedCards[Card] = decodedCards.filter(where: { referenceIds.contains([=10=].id)})
self.cards = matchedCards // factory.cards