Swift 如何实现上下文可控的快速编码功能?
我正在尝试为一个可编码结构实现一个编码器,我可以通过传递一个上下文来控制它,该上下文确定我将向输出JSON中添加哪些字段。但我想不出一个好办法 例如,假设我有以下几点:Swift 如何实现上下文可控的快速编码功能?,swift,codable,Swift,Codable,我正在尝试为一个可编码结构实现一个编码器,我可以通过传递一个上下文来控制它,该上下文确定我将向输出JSON中添加哪些字段。但我想不出一个好办法 例如,假设我有以下几点: import Foundation struct MyStruct: Encodable { var a:Int = 0 var b:Int = 0 enum CodingKeys: String, CodingKey { case a case b }
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)
}
有没有什么好的解决方案可以提供与我想象的编码(:WithContext)功能相同的效果
我有一个不太感兴趣的解决方案,就是在调用encode()之前将上下文变量添加到结构中并进行设置:
我不确定是否要将此上下文变量添加到我拥有的每个stuct中。还有更优雅的方法吗?如果您需要将一些上下文传递给
编码器
,您可以始终使用:
用户为编码而设置的任何上下文信息
例如:
struct MyStruct: Encodable {
var a:Int = 0
var b:Int = 0
enum CodingKeys: String, CodingKey {
case a
case b
}
enum Context {
case summary, full
static let encodingKey = CodingUserInfoKey(rawValue: "my_struct_context")!
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(a, forKey: .a)
if (encoder.userInfo[Context.encodingKey] as? Context) == .full {
try container.encode(b, forKey: .b)
}
}
}
var myObject = MyStruct()
myObject.a = 10
myObject.b = 5
let jsonEncoder = JSONEncoder()
jsonEncoder.userInfo = [
MyStruct.Context.encodingKey: MyStruct.Context.summary
]
do {
let jsonData = try jsonEncoder.encode(myObject)
let jsonString = String(data: jsonData, encoding: .utf8)!
print(jsonString)
} catch {
print(error)
}
为什么你写的不是一个“好的解决方案”?换句话说:为什么你写的是“虚构的”?编写自己的
encode(to)
的全部意义在于,你可以做任何你想做的事情。您实际遇到了什么问题?因为swift希望encode只有一个参数(到encoder:encoder)?我不知道如何传递上下文变量。哦!我懂了。那么,没有必要在上下文中"传递",;上下文只需要处于足够高的作用域级别,以便encode(to:)
在调用它时可以看到它。确实如此。所以我再次问,有什么问题?基本上,你的(新)代码编译得很好。顺便说一句,使用类和继承处理类似的问题也很常见(我不是说这是最好的解决方案)。很酷,我已经完全忘记了这一点!(如果我知道的话!!!)但是,在这种特殊情况下,我不明白OP的困难是什么;上下文在范围之内。这不是一个困难,因为更多的是寻找更好的解决方案——如果它们存在的话。我不想在我所有的类中添加一个上下文变量,只是想问社区是否有更好的方法我不知道-比如建议的方法。@PhilipPegden Cool,如果这是你想要的,你应该接受这个答案。
struct MyStruct: Encodable {
var a:Int = 0
var b:Int = 0
enum CodingKeys: String, CodingKey {
case a
case b
}
enum Context {
case summary, full
static let encodingKey = CodingUserInfoKey(rawValue: "my_struct_context")!
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(a, forKey: .a)
if (encoder.userInfo[Context.encodingKey] as? Context) == .full {
try container.encode(b, forKey: .b)
}
}
}
var myObject = MyStruct()
myObject.a = 10
myObject.b = 5
let jsonEncoder = JSONEncoder()
jsonEncoder.userInfo = [
MyStruct.Context.encodingKey: MyStruct.Context.summary
]
do {
let jsonData = try jsonEncoder.encode(myObject)
let jsonString = String(data: jsonData, encoding: .utf8)!
print(jsonString)
} catch {
print(error)
}