无需解码的通用可解码

时间:2018-09-27 15:18:16

标签: swift codable

我正在使用一种通用方法来解码AlamoFire生成的JSONresponse。我的功能如下:

private func fetch<T: Swift.Decodable>(URLRequest: URLRequestConvertible) -> SignalProducer<T, NetworkError> {
    return Network.request(URLRequest)
        .attemptMap { JSON in
            do {
                let jsondata = try JSONSerialization.data(withJSONObject: JSON as! [String:Any], options: .prettyPrinted)
                return .success(try JSONDecoder().decode(T.self, from: jsondata))
            } catch let error {
                Logger.shared.error("Error while decoding a JSON", error: error as NSError, userInfo: ["json" : JSON,  "urlRequest" : URLRequest.urlRequest!.debugDescription])
                return .failure(.incorrectDataReturned)
            }
    }
}

对于我的每个请求,我创建了一个遵循“可解码”协议的结构。

对于一个请求,我不想解码JSON,因为它的结构很复杂,并且因为我只需要在另一个请求中发回它,我只想将响应保存在这样的结构中: / p>

struct GenericResponse: Swift.Decodable {
    let data: Data
}

其中数据是响应。因此,我只想获取响应并将其放入结构中,而无需进一步解码。

是否可以不中断我的函数的通用性?如果T.self属于某种类型,他们是否可以构建不解码的解码器?

2 个答案:

答案 0 :(得分:1)

如果要避免解码特定的响应,可以重载fetch函数来处理这种情况。

请参见以下示例,其中第二次访存method被重载以将响应数据保存在结构体中,而不是通过解码过程。

typealias JSON = [String: Any]

protocol RawResponse {
  init(data: Data)
}

// 1
func fetch<T: Decodable>(json: JSON) -> T? {
  guard let jsonData = try? JSONSerialization.data(withJSONObject: json, options: []),
    let response = try? JSONDecoder().decode(T.self, from: jsonData) else {
      return nil
  }
  return response
}

// 2
func fetch<T: RawResponse>(json: JSON) -> T? {
  guard let jsonData = try? JSONSerialization.data(withJSONObject: json, options: []) else {
    return nil
  }
  return T(data: jsonData)
}

使用这种重载,如果响应struct符合RawResponse而不是Decodable(因为我们不需要实际解码数据),则fetch重载被触发。

struct UserResponse: Decodable {
  var username: String
}

let userJson: JSON = [
  "username": "someUser"
]
let user: UserResponse? = fetch(json: userJson) // call fetch #1
user?.username // someUser


struct GenericResponse: RawResponse {
  var data: Data
}

let notParsable: JSON = [
  "someKey": "someValue"
]
let rawData: GenericResponse? = fetch(json: notParsable) // call fetch #2
rawData?.data // 23 bytes

答案 1 :(得分:0)

我不太了解您要达到的目标。但是我遇到这种情况,需要使用泛型进行解码。

这就是为什么我编写了一个DecoderHelper类,该类使我能够解码通用数组或通用对象(取决于您的JSON响应)。

也许它可以激发您的灵感,您将找到如何对其进行优化或了解您的处境/问题。

class Foo(models.Model):
    ...
    def call_all_bars(self):
        for base in self.bases.all():
            base.bar()

PS:为什么由于“ JSON结构太复杂”而希望将其发送到其他请求?

现在使用Codable协议解析JSON文件非常简单。

尝试一下并进行自我训练,现在,我已经习惯了,我喜欢解析JSON。