利用 Decoder 來解析 JSON 要懂的那些方法

隨著 App 的普及,在百家爭鳴下使用者對 UI/UX 的要求也逐漸的提高,這使得 App 所需要的資料也相對的比以前要複雜上幾倍,很多情況後端給的資料仍不足以滿足 App 端的需求,此時就得在 decode 時,將其轉換成 App 端可用的資料,而在進行資料轉換時,有幾個方法就特別重要,也很容易搞混,因為其方法名稱很像,哪些方法呢?也就是今天的四個主角。先讓法蘭克稍加介紹這幾個方法,最後會舉一個情境來使用它們。

法蘭克的 iOS 世界
5 min readDec 3, 2020

方法解釋

在 Decodable 的建構子中 Decode 時,常常會用到的以下幾個方法。

nestedContainer(keyedBy:forKey:):從 JSON 中取得指定的 key 值的 Object

nestedContainer(keyedBy:forKey:)

此方法有兩個參數,第一個參數必須傳入遵從 Codingkeys protocol 的 Enum,第二個參數則為 Enum 的 key 值(圖1),最終會回傳方法所指定的 Key 值的 Container,其 Container 對應到 JSON 為一個 Object

圖1

nestedUnkeyedContainer(forKey:):從 JSON 中取得指定的 key 值的 Array

nestedUnkeyedContainer(forKey:)

與前方法不同的是,此方法只有一個參數,僅需傳入 Enum 的 key 值,最終會回傳方法所指定的 Key 值的 Container,其 Container 對應到 JSON 為一個 Array

nestedContainer(keyedBy:):從陣列中取得指定的 key 值的 Object

nestedContainer(keyedBy:)

此方法只有一個參數,傳入遵從 Codingkeys protocol 的 Enum,此方法應用場景在迴圈裡

nestedUnkeyedContainer():從陣列中取得下一個陣列

nestedUnkeyedContainer()

此方法不需參數,此方法應用場景在迴圈裡

針對上述四個方法做個小結,nestedContainer(keyedBy:forKey:) 和 nestedUnkeyedContainer(forKey:) 這前兩個方法需要 Enum 的 Key 值,因它們會依指定的 Key 值在迴圈外取得其相對應的資料;nestedContainer(keyedBy:) 和 nestedUnkeyedContainer() 則不需要 Enum 的 Key 值,因它們總是在迴圈內被使用。

使用方式

以下情境為使用前半段提到的四種方法來解析 JSON,過程中僅僅將 JSON 的資料完整的 Parse 成相對應的欄位,但在實務上,通常會需要客製成複和的欄位、經過計算的欄位等等情境,這邊就不多加贅述,此情境的重點會放在前述四個方法的應用。

#1

定義用來 Decode 的 JSON 物件,在開始範例前,先仔細看一下此結構,有助於閱讀上的理解。

#2

定義用來 Parse JSON 的 Struct,可使用 QuickType 快速建立。

#3

首先,必須先宣告 Decodable 的建構子,並從其注入的 decoder 開始,取得 JSON 最外層的 Container,而這也是 Parse 此 JSON 物件的起點,根據 #1 的 JSON 物件,userID、age、name 屬最外層的欄位,在 Decode 時,直接從 rootContainer decode 即可。

#4

接著,要 decode country 和 city,就得必須使用 nestedContainer(keyedBy:forKey:) 來取得第二層的 residence。

#5

要解析 friend 陣列,就得必須使用 nestedUnkeyedContainer(forKey:) + nestedContainer(keyedBy:) 組合技,前者可解析 JSON object array 後者則可以解析迴圈裡的 Object,isAtEnd() 可用來判斷是否是最後一筆資料了。

#6

最後,要解析 skill 裡依 type 分類的 skill,其資料結構為二維陣列,就得必須使用 nestedUnkeyedContainer(forKey:) + nestedUnkeyedContainer() 組合技,前者可解析 JSON object array 後者則可以向下再解析 Array。

如果您喜歡我的文章,請多按幾下「拍手」給我鼓勵,或是按「follow」讓我持續提供好文章給您。

--

--