Swift 可以实现Void和Codable的泛型

Swift 可以实现Void和Codable的泛型,swift,Swift,这里我有一个用于api结果的结构 struct Response<Result> { let status: Int let message: String let result: Result } 我遇到的问题是,一些响应没有result键,我希望能够像Void类型一样使用Response对象,而不是Response 目前我有一种可能的解决方法,只需声明另一个响应类型,其中没有结果变量,如下所示: struct BaseResponse { let

这里我有一个用于api结果的结构

struct Response<Result> {
    let status: Int
    let message: String
    let result: Result
}
我遇到的问题是,一些响应没有
result
键,我希望能够像
Void
类型一样使用
Response
对象,而不是
Response

目前我有一种可能的解决方法,只需声明另一个
响应
类型,其中没有
结果
变量,如下所示:

struct BaseResponse {
    let status: Int
    let message: String
}
init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)

    status = try container.decode(Int.self, forKey: .status)
    message = try container.decode(String.self, forKey: .message)

    if Result.self is Nothing.Type {
        result = Nothing() as! Result
    } else {
        result = try container.decode(Result.self, forKey: .result)
    }
}
有没有办法避免我声明另一个
Response
类型


我试着做了以下几件事,但都不管用

  • 我无法使
    Void
    符合
    Codable
  • 另一个扩展符合codable,其中
    结果:Void
  • 从不
    也将不起作用,因为它没有自己的初始值设定项,因此我无法将其与
    可编码
  • 创建一个符合
    Codable
    Nothing
    类型,如下所示
  • 所以我可以用这样的回答

    let response: Response<Nothing> = Response(
        status: 200,
        message: "Success",
        result: .nothing
    )
    
    or
    
    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.status = try container.decode(forKey: .status)
        self.message = try container.decode(forKey: .message)
    
        // These lines don't work.
        if let result = try container.decodeIfPresent(Result.self, forKey: .result) {
            self.result = result
        } else {
            self = .nothing
        }
    }
    
    let response:response=response(
    现状:200,
    信息:“成功”,
    结果:。没有
    )
    或
    public init(来自解码器:解码器)抛出{
    let container=try decoder.container(keyedBy:CodingKeys.self)
    self.status=try container.decode(forKey:.status)
    self.message=try container.decode(forKey:.message)
    //这些线不行。
    如果let result=try container.decodeIfPresent(result.self,forKey:.result){
    self.result=结果
    }否则{
    self=。什么都没有
    }
    }
    

    但问题是我不能为
    Nothing
    类型指定
    decodeIfPresent
    方法。到此为止。

    结果制作成
    可选的
    类型
    结果?
    。现在,当响应包含针对
    result
    键的值时,它将在
    result
    属性中设置。否则,如果不存在
    结果
    键,它将保持为
    nil

    struct Response<Result: Codable>: Codable {
        let status: Int
        let message: String
        let result: Result? //here....
    }
    
    struct响应:可编码{
    let状态:Int
    让消息:字符串
    让结果:结果?//这里。。。。
    }
    
    解析如下数据:

    do {
        let response = try JSONDecoder().decode(Response<String>.self, from: data)
        print(response)
    } catch {
        print(error)
    }
    
    do{
    让response=try JSONDecoder().decode(response.self,from:data)
    打印(答复)
    }抓住{
    打印(错误)
    }
    
    根据您的要求,在
    响应中使用您想要的任何类型

    示例:

  • 如果JSON是
    {“状态”:1,“消息”:“这是一条消息”,“结果”:“QWERTY”}
  • 然后
    response
    是,
    response(状态:1,消息:“这是一条消息”,结果:可选(“QWERTY”)

  • 如果JSON是
    {“status”:1,“message”:“这是一条消息”}

  • 然后
    response
    是,
    response(状态:1,消息:“这是一条消息”,结果:nil))

    您可以像这样定义
    init(from:)
    方法:

    struct BaseResponse {
        let status: Int
        let message: String
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
    
        status = try container.decode(Int.self, forKey: .status)
        message = try container.decode(String.self, forKey: .message)
    
        if Result.self is Nothing.Type {
            result = Nothing() as! Result
        } else {
            result = try container.decode(Result.self, forKey: .result)
        }
    }
    

    您检测到您处于
    响应
    情况,并完全跳过对结果的解码。这样,在需要结果的情况下,您可以保持正常的
    结果
    解码,并且可以将其保留为非可选的。

    只需在
    响应
    中去掉泛型,并将
    结果
    设置为可选,但这将无法将
    结果
    作为泛型参数,我还不如把它做成
    result:Any?
    ,这样似乎就可以了。你确定你需要使用泛型吗?是的,这样我就不用做空检查了。是的,我明白了,这是我最初的实现,但是这样做意味着我必须对
    结果
    执行空检查,这是我不想做的,这就是为什么我创建了另一个ResponseType,其中没有
    结果
    。但是在中,也不需要检查结果类型。在任何情况下,当使用结果时,您需要检查结果中是否有任何值。我认为这会导致崩溃,但它起到了作用。我尝试使用扩展
    扩展响应来实现这一点,结果是:什么都没有
    扩展响应
    ,但它不起作用。
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
    
        status = try container.decode(Int.self, forKey: .status)
        message = try container.decode(String.self, forKey: .message)
    
        if Result.self is Nothing.Type {
            result = Nothing() as! Result
        } else {
            result = try container.decode(Result.self, forKey: .result)
        }
    }