【发布时间】:2019-02-24 16:17:04
【问题描述】:
我正在尝试为 Codable 结构实现编码器,我可以通过传递一个上下文来控制它,该上下文确定我将添加到输出 JSON 中的字段。但我想不出一个好的方法。
例如说我有以下内容:
import Foundation
struct MyStruct: Encodable {
var a:Int = 0
var b:Int = 0
enum CodingKeys: String, CodingKey {
case a
case b
}
enum Context {
case summary, full
}
// I can write something like this
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(a, forKey: .a)
try container.encode(b, forKey: .b)
}
// ...but I want to write is something like this
func encode(to encoder: Encoder, withContextcontext: Context ) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(a, forKey: .a)
if context == .full
{
try container.encode(b, forKey: .b)
}
}
}
var myObject = MyStruct()
myObject.a = 10
myObject.b = 5
let jsonEncoder = JSONEncoder()
do {
let jsonData = try jsonEncoder.encode(myObject)
// let jsonData = try jsonEncode.encode(myObject, withContext:.full)
let jsonString = String(data: jsonData, encoding: .utf8)!
print(jsonString)
} catch {
print(error)
}
有没有什么好的解决方案可以产生与我想象中的 encode(:WithContext) 功能相同的效果?
我有一个我不太喜欢的解决方案是将上下文变量添加到结构中并在调用 encode() 之前对其进行设置:
struct MyStruct: Encodable {
var a:Int = 0
var b:Int = 0
var context = .full
enum CodingKeys: String, CodingKey {
case a
case b
}
enum Context {
case summary, full
}
// But I want to write is something like this
func encode(to encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(a, forKey: .a)
if context == .full
{
try container.encode(b, forKey: .b)
}
}
}
var myObject = MyStruct()
myObject.a = 10
myObject.b = 5
myObject.context = .summary
let jsonEncoder = JSONEncoder()
do {
let jsonData = try jsonEncoder.encode(myObject)
let jsonString = String(data: jsonData, encoding: .utf8)!
print(jsonString)
} catch {
print(error)
}
不确定我是否要将此 Context 变量添加到我拥有的每个结构中。还有更优雅的方式吗?
【问题讨论】:
-
为什么你写的不是一个“好的解决方案”?换句话说:为什么你写的是“虚构的”?编写自己的
encode(to)的全部意义在于,您可以为所欲为。你有什么实际问题? -
因为 swift 期望 encode 只有一个参数(对编码器:编码器)?我不确定如何传入上下文变量。
-
哦!我懂了。好吧,没有必要“传入”上下文;上下文只需要生活在足够高的范围内,
encode(to:)可以在调用它时看到它。它确实如此。所以我再次问,有什么问题?基本上你的(新)代码编译得很好。 -
顺便说一句,使用类和继承处理类似问题也很常见(我并不是说这是最好的解决方案)。