簡體   English   中英

迅捷:可腐爛

[英]Swift: Decodable

可以說我有一個來自API請求的json:

friends: {  
   "john":31,
   "mark":27,
   "lisa":17,
   "tom":41
}

我通常期望它采用數組格式:

friends: [  
   { "john":31 },
   { "mark":27 },
   { "lisa":17 },
   { "tom":41 }
]

但是API不會以這種方式向我提供結果。 所以我最終希望將其映射到[Friend]的數組,其中Friend是:

class Friend: Decodable {
  let name: String
  let age: Int
}

我應該如何序列化此json以獲取[Friend]?

首先,示例根本不是有效的json。 為了有效,它要么不應該包含“ friends”標簽,要么應該嵌入到另一個這樣的對象中

{
  "friends": {  
    "john":31,
    "mark":27,
    "lisa":17,
    "tom":41
  }
}

如果我正確理解問題,則想將json對象解碼為swift數組。 我認為沒有編寫自定義解碼的方法是不可能的。 相反,您可以將json解碼為Dictionary並在手動映射時像這樣

struct Friend {
    let name: String
    let age: Int
}

struct Friends: Decodable {
    let friends: [String: Int]
}

let friends = try! JSONDecoder().decode(Friends.self, from: json.data(using: .utf8)!)
    .friends
    .map { (name, age) in Friend(name: name, age: age) }

免責聲明 :我建議將您的API格式更改為@scriptable的答案中的一種 (我在回答時已刪除,hm),其中正確定義了nameage字段。 而且您基本上不局限於要解析的一對鍵值。

但是,如果您無法更改,則可以使用如下所示的方式來解碼您的Friend類型:

struct Friend: Decodable {
    let name: String
    let age: UInt

    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        let dictionary = try container.decode([String: UInt].self)

        guard dictionary.count == 1, let (name, age) = dictionary.first else {
            throw DecodingError.invalidFriendDictionary
        }

        self.name = name
        self.age = age
    }

    enum DecodingError: Error {
        case invalidFriendDictionary
    }
}

struct Friends: Decodable {
   let friends: [Friend]
}

let friends = try JSONDecoder().decode(Friends.self, from: data)

它假定keynamevalueage 並檢查是否只有一對要解析。

暫無
暫無

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

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