Swift JSONDecode 解碼陣列在單個元素解碼失敗時也會失敗


在 Swift 中,使用 JSONDecoder 類處理 JSON 物件非常容易。始終需要使用 Codable 協議建立模型類或結構體。一個小的錯誤會導致無法解碼整個 JSON 物件。讓我們探索一些示例,以瞭解何時可能發生此錯誤以及如何在 Swift 中處理它。

什麼是 JSONDecoder 類?

然後使用 JSONDecoder 類將 JSON 資料從檔案解析為給定型別的例項,可以是類或結構體。decode(_:from:) 方法用於反序列化 JSON 資料,然後返回生成的 Type 物件以訪問 Type 物件的屬性。

我們嘗試使用 Codable 協議讀取上面給出的相同 JSON 作為示例。在準備好使用 JSONDecoder() 類解碼 JSON 資料之前,讓我們準備在解碼時提供的模型類。

這是一個建立此錯誤條件的示例

步驟 1 - 建立 JSON 檔案

在此步驟中,我們將建立一個示例 JSON 並將其另存為 Xcode 專案中的“.json”檔案。這是我們在此示例中將使用的 JSON:

[
   {
      "name": "Tom Cruise",
      "age": 56,
      "bornAt": "Syracuse, NY",
      "birthdate": "July 3, 1962",
      "photo": "https://jsonformatter.org/img/tom-cruise.jpg",
      "topMovie": "Mission Impossible"
   },
   {
      "name": "Robert Downey Jr.",
      "age": 53,
      "bornAt": "New York City, NY",
      "birthdate": "April 4, 1965",
      "photo": "https://jsonformatter.org/img/Robert-Downey-Jr.jpg"
   }
]

我們將此 JSON 檔案命名為“sample.json”並儲存在專案目錄中。

步驟 2 - 建立模型結構

此步驟涉及建立名為“Actor”的結構體並符合 Decodable 協議。程式碼如下:

import Foundation
struct Actor: Decodable {
   let name: String
   let age: Int
   let bornAt: String
   let birthdate: String
   let photo: String
   let topMovie: String
}

步驟 3 - 將 JSON 解碼為 Actor 結構體

在此步驟中,我們將解碼 JSON 檔案並將資料儲存到 Actor 模型中。程式碼如下:

import UIKit
class CodableController: UIViewController {
       
   override func viewDidLoad() {
      super.viewDidLoad()
      decodeJSON()
   }
   func decodeJSON() {
      do {
         // creating path from the main bundle and getting data object from the path
         if let bundlePath = Bundle.main.path(forResource: "sample", ofType: "json"),
         let jsonData = try String(contentsOfFile: bundlePath).data(using: .utf8) {
                         
            let actors = try JSONDecoder().decode([Actor].self, from: jsonData)
            print("Number of actors parsed: \(actors.count)")
         }
      } catch {
         print(error)
      }
   }
}

在上面的示例中,我們建立了一個名為“CodableController”的檢視控制器以及一個方法。在此方法中,我們正在從主 bundle 讀取本地 JSON 檔案。之後,我們使用 JSONDecoder().decode() 方法解碼 JSON 資料。我們將型別“[Actor].self”傳遞給 decode 方法,如果成功解碼,則該方法將返回演員物件的陣列。

在此示例中,json 變數包含兩個物件的陣列,其中第二個物件無效(缺少必需的屬性)。JSONDecoder 用於解碼每個物件,並且在解碼過程中發生的任何錯誤都會被捕獲並列印到控制檯。成功解碼的物件將新增到名為 actors 的陣列中。示例的輸出將是:

keyNotFound(CodingKeys(stringValue: "topMovie", intValue: nil), Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 1", intValue: 1)], debugDescription: "No value associated with key CodingKeys(stringValue: "topMovie", intValue: nil) ("topMovie").", underlyingError: nil))

如您所見,由於 JSON 資料中缺少值,解碼過程失敗。可以清楚地說,鍵“topMovie”的值丟失了。

步驟 4 - 修復錯誤

在此步驟中,我們將嘗試修復上述錯誤。根據 JSON 檔案,第二個物件缺少“topMovie”鍵。如果您認為此值不需要在應用程式中執行進一步的操作,則可以將其設為可選,如下所示:

import Foundation
struct Actor: Decodable {
   let name: String
   let age: Int
   let bornAt: String
   let birthdate: String
   let photo: String
   let topMovie: String?
}

現在,您可以再次執行程式碼,您將在控制檯中看到列印的輸出:

Number of actors parsed: 2

如您所見,解碼過程已成功完成,沒有錯誤。

結論

Swift 提供了 JSONDecoder 類來將 JSON 物件編碼和解碼為 Swift 的模型物件,反之亦然。我們有責任仔細處理屬性宣告,否則會導致錯誤。

對於 JSON 物件中缺少的值,可以將這些變數設為可選。鑑於這些值可能不會出現在伺服器響應中,因此建議將它們設為可選。

另一種解決此問題的方法是使用另一種解碼技術,該技術分別解碼每個物件並丟棄任何解碼錯誤。即使無法解碼一個或多個元素,這也能使解碼繼續進行。

您可以透過呼叫 JSONDecoder 例項的 decode( :from:completionHandler:) 方法並向其傳遞一個接受 Result 物件作為引數的閉包來應用自定義解碼方法。Result 物件包含正確解碼的專案陣列或錯誤。

更新於:2023年4月11日

215 次瀏覽

開啟你的 職業生涯

透過完成課程獲得認證

開始學習
廣告
© . All rights reserved.