Swift 疑問 — JSONSerialization 的 Options?

究竟 JSONSerialization 的方法中的 Options 參數到底幫我們做了什麼事情呢?

Jeremy Xue
6 min readFeb 26, 2019
Photo by Daniil Silantev on Unsplash

前言:

最近打算整理一些無論是個人或是工作室的大家、學員在開發間所碰到的問題,針對碰到的問題內容來深入的研究,會盡量把提出的疑惑給正確解決,但也有可能遇上無法解釋的狀況,例如:Bug 無法重現之類的…。

因為有些問題可能我也不了解內部發生了什麼原因,所以想藉由這個過程了解到這個問題過程發生了什麼,並且一一去解釋原因,藉由這樣也能使自己多了解一些問題、或是 Bug,同時也能解決他們的疑惑。

發生情況:

前陣子在工作室在進行小型 Side Project 活動時,當時候有人在進行透過 API 將參數發送給後端這邊碰到了問題,每次發送的 request 後得到的 response 都是沒有帶上參數,而她是使用 try? 配合 JSONSerialization 在進行將 Dictionary ( JSON ) 類型轉換成 Data? 作為請求的 httpBody 發送。

而我們實際將他的 httpBody 再次解析成 JSON,也是得到相同的內容。

  • 意外的解決?我不這麼認為 🤨

而這時候有人使用 do-catch 的方式來執行 JSONSerializationdata(withJSONObject:options:) 的方法,並且在其 options 參數中加上了一個 JSONSerialization.WritingOptions() 的實例化,接著發送請求並且得到後端正確的返回值。

這時讓我一頭霧水,因為我覺得會有以下幾點問題

  1. httpBody 的參數可以讓你賦與一個 Data? 類型的值,畢竟原本經由我們透過 try? 以及JSONSerialization 轉換成 Data 的返回值就是為 Data? 類型,所以我不認為還需要使用 do-catch 方式來處理會有差異( 除非想要看到JSONSerialization 的錯誤描述 )。
  2. JSONSerialization.WritingOptions() 這個實例化到底實例化了什麼?因為就我的了解,這個 options 參數所能帶入的類型應該為一個 JSONSerialization.WritingOptions 類型的值(原本以為它是一個 Enumeration 類型的值,後來發現是 struct ),但也只有 .sortedKeys.prettyPrinted 兩種值可以採用,而透過 rawValue 所初始化出來的又是什麼?
  3. 但是它對於後端的其他請求沒有加上 options 參數卻還是能透過,所以我覺得只有這個請求要加上 options 並不合理,照理說也不需要。

後來採用原本的不加上 options 方式,莫名其妙地得到後端正確的回傳…

一個無法重現的 Bug 啊~ 😭😭😭

● JSONSerialization 的 Options

在我們使用 JSONSerialization 對於 data 以及 jsonObject 兩種方法也有不同的 options 可以採用,分別為 WritingOptions 以及 ReadingOptions ,讓我們來分別認識這兩者:

WritingOptions,用來編寫 JSON 數據的選項。

- prettyPrinted
此選項藉由使用空格及縮排讓輸出結果更具可讀性。
- sortedKeys
此選項會讓結果按字典中的key值進行排序。

ReadingOptions,從 JSON 數據創建 Foundation Objects 時使用的選項。

- mutableContainers
指定將數組和字典創建為可變對象。
- mutableLeaves
指定將 JSON 對象圖中的字串創建為 NSMutableString 的實例。
- allowFragments
指定解析器(Parser)允許不是 NSArray 或 NSDictionary 為頂層對象的實例。

並且這兩者都有一個 init(rawValue: UInt) 方法,但是透過它初始化出來的值不知道是什麼用途。

而我在 stack overflow 上的這篇文章找尋到類似的問題,只是它想要找 ReadingOptions 的功用,而下面回覆提到了:

⚠️ 在 Swift 中請忽略它們在 Swift 中你可以透過使用 var 使對象變為可變;而在 Objective-C 則需要透過這種方式,使一個 Array 或是 Dictionary 變為可變的。在 Objective-C 和 Swift 中,如果您只是閱讀JSON,則不需要可變性。

WritingOptions 在我測試的時候,好像就算帶上 options 也沒有效果,好像沒有看到官方文檔內的效果(又或許它已經自動幫我們實現了):

後記:

這可能是我第一篇文章寫到不知道如何下手的,尤其許多地方都好像無從解釋,像是 Bug 無法重現和 optionsrawValue 到底初始化了什麼,以及最後在 options 帶參數和不帶參數的差異在哪?雖然官方文檔有提供說明該值的作用是什麼,但也沒有實際的範例或是說明這種方法是否可行,又或是說明 Objective-C 需要,Swift 不需要之類的訊息。

如果有寫錯的部分或是有人可以幫忙解答的部分,歡迎各位在下方留言指教,希望能將正確的資訊帶給大家。

參考來源:

--

--

Jeremy Xue

Hi, I’m Jeremy. [好想工作室 — iOS Developer]