我用于后端调用的服务返回所有以下json结构:
{
"status" : "OK",
"payload" : **something**
}
某物可以是简单字符串的地方:
{
"status" : "OK",
"payload" : "nothing changed"
}
或嵌套的json(具有任何属性的json),例如:
{
"status" : "OK",
"payload" : {
"someInt" : 2,
"someString" : "hi",
...
}
}
这是我的结构:
struct GenericResponseModel: Codable {
let status:String?
let payload:String?
}
我想始终将“有效载荷”解码为字符串。因此,在第二种情况下,我希望“ GenericResponseModel”的有效负载属性包含该字段的json字符串,但是如果尝试解码该响应,则会收到错误消息:
Type 'String' mismatch: Expected to decode String but found a dictionary instead
可以存档我想要的东西吗?
非常感谢
答案 0 :(得分:1)
怎么样……
声明一个PayloadType
协议…
protocol PayloadType: Decodable { }
并使String
和struct Payload
符合它…
extension String: PayloadType { }
struct Payload: Decodable, PayloadType {
let someInt: Int
let someString: String
}
然后将GenericResponseModel
设为通用…
struct GenericResponseModel<T: PayloadType>: Decodable {
let status: String
let payload: T
enum CodingKeys: CodingKey {
case status, payload
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
status = try container.decode(String.self, forKey: .status)
payload = try container.decode(T.self, forKey: .payload)
}
}
然后您可以解码如下...
let data = """
{
"status" : "OK",
"payload" : "nothing changed"
}
""".data(using: .utf8)!
print(try JSONDecoder().decode(GenericResponseModel<String>.self, from: data))
// GenericResponseModel<String>(status: "OK", payload: "nothing changed")
和
let data2 = """
{
"status" : "OK",
"payload" : {
"someInt" : 2,
"someString" : "hi"
}
}
""".data(using: .utf8)!
print(try JSONDecoder().decode(GenericResponseModel<Payload>.self, from: data2))
// GenericResponseModel<Payload>(status: "OK", payload: Payload(someInt: 2, someString: "hi"))
当然,这取决于您事先知道payload
类型。如果有效载荷的类型错误,您可以通过抛出特定错误来解决此问题……
enum GenericResponseModelError: Error {
case wrongPayloadType
}
然后……
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
status = try container.decode(String.self, forKey: .status)
do {
payload = try container.decode(T.self, forKey: .payload)
} catch {
throw GenericResponseModelError.wrongPayloadType
}
}
然后在解码时处理此错误……
let data = """
{
"status" : "OK",
"payload" : {
"someInt" : 2,
"someString" : "hi"
}
}
""".data(using: .utf8)!
do {
let response = try JSONDecoder().decode(GenericResponseModel<String>.self, from: data) // Throws
print(response)
} catch let error as GenericResponseModelError where error == .wrongPayloadType {
let response = try JSONDecoder().decode(GenericResponseModel<Payload>.self, from: data2) // Success!
print(response)
}
答案 1 :(得分:-3)
I think this is working for you
struct GenericResponseModel: Codable {
let status: String?
let payload: Payload?
}
struct Payload: {
let someInt: Int?
let someString: String?
}