簡體   English   中英

Swift 4.1可編碼/可分解嵌套數組

[英]Swift 4.1 Codable/Decodable Nested Array

需要使用最新的swift4.1編碼器/解碼器的更復雜的json的幫助:

結構:

struct LMSRequest: Decodable {
let id : Int?
let method : String?
let params : [String]?
enum CodingKeys: String, CodingKey {
    case id = "id"
    case method = "method"
    case params = "params"
}
init(from decoder: Decoder) throws {
    let values = try decoder.container(keyedBy: CodingKeys.self)
    id = try values.decodeIfPresent(Int.self, forKey: .id)
    method = try values.decodeIfPresent(String.self, forKey: .method)
    params = try values.decodeIfPresent([String].self, forKey: .params)
}}

JSON:

let json = """
{
  "id": 1,
  "method": "slim.request",
  "params": [
    "b8:27:eb:db:6d:62",
    [
      "serverstatus",
      "-",
      1,
      "tags:GPASIediqtymkovrfijnCYXRTIuwxNlasc"
    ]
  ]
}
""".data(using: .utf8)!

碼:

let decoder = JSONDecoder()
let lms = try decoder.decode(LMSRequest.self, from: json)
print(lms)

解碼字符串時會出現錯誤,但找到了數組。 它來自“ params”數組中的嵌套數組...真的停留在如何構建它上,謝謝!

根據您的描述,應該將參數存儲為如下枚舉:

enum Param: CustomStringConvertible {
    case string(String)
    case int(Int)
    case array([Param])

    var description: String {
        switch self {
        case let .string(string): return string
        case let .int(int): return "\(int)"
        case let .array(array): return "\(array)"
        }
    }
}

參數可以是字符串,整數或更多參數的數組。

接下來,您可以依次嘗試每個選項,以使Parade Decodable:

extension Param: Decodable {
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if let string = try? container.decode(String.self) {
            self = .string(string)
        } else if let int = try? container.decode(Int.self) {
            self = .int(int)
        } else {
            self = .array(try container.decode([Param].self))
        }
    }
}

鑒於此,在LMSRequest中不需要自定義解碼邏輯:

struct LMSRequest: Decodable {
    let id : Int?
    let method : String?
    let params : [Param]?
}

附帶說明一下,我會仔細考慮這些字段是否都是真正可選的。 id是可選的,這是非常令人驚訝的, method是可選的,並且params是可選的,這是非常令人驚訝的。 如果它們不是真正可選的,則不要在類型中使它們成為可選的。


從您的評論中,您可能會誤解如何訪問枚舉。 params[1]不是[Param] 這是一個.array([Param]) 因此,您必須對其進行模式匹配,因為它可能是字符串或整數。

if case let .array(values) = lms.params[1] { print(values[0]) }

就是說,如果您經常這樣做,則可以使用Param上的擴展程序使其更簡單:

extension Param {
    var stringValue: String? { if case let .string(value) = self { return value } else { return nil } }
    var intValue: Int? { if case let .int(value) = self { return value } else { return nil } }
    var arrayValue: [Param]? { if case let .array(value) = self { return value } else { return nil } }

    subscript(_ index: Int) -> Param? {
        return arrayValue?[index]
    }
}

這樣,您可以說出以下內容:

let serverstatus: String? = lms.params[1][0]?.stringValue

這可能更接近您的想法。 : String?只是為了明確返回的類型;它不是必需的。)

有關此方法的更復雜且可行的示例,請參見我的通用JSON Decodable ,它是該方法的子集。

暫無
暫無

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

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