簡體   English   中英

Swift Codable 嵌套 json 作為字符串

[英]Swift Codable with nested json as string

我用於后端調用的服務返回所有這些 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

可以存檔我想要的嗎?

非常感謝

這個怎么樣…

聲明一個PayloadType協議......

protocol PayloadType: Decodable { }

並使Stringstruct 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)
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM