英文:
Swift encoding: multiple .encode strategeis?
问题
class TestModel {
enum CodingKeys: String, CodingKey {
case someKey = "some_key"
case otherKey = "other_key"
case thirdKey = "third_key"
case apiID = "id"
// ... lots of other keys
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(someKeyValue, forKey: .someKey)
try container.encode(otherKeyValue, forKey: .otherKey)
try container.encode(thirdKeyValue, forKey: .thirdKey)
// ... lots of other encoded fields
}
}
上述代码是一个名为 TestModel
的模型,用于将数据编码为 JSON 以发送到 API。但有时我希望向不同的终端发送请求,仅更新单个属性。更新始终针对相同的属性。目前,我在 encode()
中发送所有数据,这会导致大量的带宽浪费。
我相信有一种简单的方法可以做到这一点,但文档/谷歌/stackoverflow 并没有提供有用的信息。所以,您对如何创建一个类似下面的第二个编码策略并调用它有什么想法吗?
func encodeForUpdate(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(apiID, forKey: .apiID)
try container.encode(justOneValueToUpdate, forKey: .someKey)
}
英文:
I have a model TestModel
that encodes data to JSON to send to an API. It looks like this:
// Called by: JSONEncoder().encode(testModelObject)
class TestModel {
enum CodingKeys: String, CodingKey {
case someKey = "some_key"
case otherKey = "other_key"
case thirdKey = "third_key"
case apiID = "id"
// ... lots of other keys
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(someKeyValue, forKey: .someKey)
try container.encode(otherKeyValue, forKey: .otherKey)
try container.encode(thirdKeyValue, forKey: .thirdKey)
// ... lots of other encoded fields
}
}
The above works fine, however sometimes I wish to send a request to a different endpoint that updates just a single attribute. The update is always going to be for the same attribute. At present I'm sending through all data in encode(), which equals a lot of wasted bandwidth.
I'm sure there's an easy way to do this, but docs/google/stackoverflow aren't proving helpful. So: any thoughts on how to create a second encoding strategy along the lines of the below and call it?
func encodeForUpdate(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(apiID, forKey: .apiID)
try container.encode(justOneValueToUpdate, forKey: .someKey)
}
答案1
得分: 2
需要有一个名为encode(to encoder: Encoder)
的单一函数,但您可以通过使用特定的CodingKey
枚举来解决这个问题。
enum SimpleCodingKeys: String, CodingKey {
case thirdKey = "third_key"
case apiID = "id"
}
然后使用JSONEncoder
的userInfo
属性来告诉何时使用这个第二个枚举。首先,我们需要一个键:
extension TestModel {
static var useSimpleCodingKeys: CodingUserInfoKey {
return CodingUserInfoKey(rawValue: "useSimpleCodingKeys")!
}
}
然后调整编码函数:
func encode(to encoder: Encoder) throws {
let useSimple = encoder.userInfo[Self.useSimpleCodingKeys] as? Bool ?? false
if useSimple {
var container = encoder.container(keyedBy: SimpleCodingKeys.self)
try container.encode(apiID, forKey: .apiID)
try container.encode(thirdKeyValue, forKey: .thirdKey)
} else {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(someKeyValue, forKey: .someKey)
try container.encode(otherKeyValue, forKey: .otherKey)
try container.encode(thirdKeyValue, forKey: .thirdKey)
// ...
}
}
当编码时,当然要在字典中设置这个值:
let encoder = JSONEncoder()
encoder.userInfo[TestModel.useSimpleCodingKeys] = true
英文:
You need to have a single encode(to encoder: Encoder)
function but you can solve this by using a specific CodingKey
enum for the second strategy
enum SimpleCodingKeys: String, CodingKey {
case thirdKey = "third_key"
case apiID = "id"
}
and then use the userInfo
property of JSONEncoder
to tell when you want to use this second enum. First we need a key to use
extension TestModel {
static var useSimpleCodingKeys: CodingUserInfoKey {
return CodingUserInfoKey(rawValue: "useSimpleCodingKeys")!
}
}
and then adjust the encoding function
func encode(to encoder: Encoder) throws {
let useSimple = encoder.userInfo[Self.useSimpleCodingKeys] as? Bool ?? false
if useSimple {
var container = encoder.container(keyedBy: SimpleCodingKeys.self)
try container.encode(apiID, forKey: .apiID)
try container.encode(thirdKeyValue, forKey: .thirdKey)
} else {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(someKeyValue, forKey: .someKey)
try container.encode(otherKeyValue, forKey: .otherKey)
try container.encode(thirdKeyValue, forKey: .thirdKey)
...
}
}
And of course set this value in the dictionary when encoding
let encoder = JSONEncoder()
encoder.userInfo[TestModel.useSimpleCodingKeys] = true
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论