Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 如何实现上下文可控的快速编码功能?_Swift_Codable - Fatal编程技术网

Swift 如何实现上下文可控的快速编码功能?

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 }

我正在尝试为一个可编码结构实现一个编码器,我可以通过传递一个上下文来控制它,该上下文确定我将向输出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)
}
有没有什么好的解决方案可以提供与我想象的编码(: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)
}