<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Codable發(fā)布這么久我就不學,摸魚爽歪歪,哎~就是玩兒

          共 42164字,需瀏覽 85分鐘

           ·

          2021-05-12 09:58

          寫在開頭

          祝天下所有偉大的母親:

          節(jié)日快樂,身體健康, 感謝您的付出,感謝您的仁愛!

          ----- 寫在母親節(jié)當天

          前言

          對于大多數(shù)的應用程序來說,最常見的任務就是進行網(wǎng)絡數(shù)據(jù)的發(fā)送和接收,但是在執(zhí)行此操作之前,我們需要通過編碼或者序列化的方式將數(shù)據(jù)轉(zhuǎn)換為合適的格式來發(fā)送,然后還需要將收到的網(wǎng)絡數(shù)據(jù)轉(zhuǎn)換為合適的格式,這樣才能在應用中使用它們,這樣的過程叫做解碼或著叫反序列化。

          那如何去定義這個格式呢!這里就不得不提 JSON 了,JSON 目前是網(wǎng)絡通信發(fā)送和接收數(shù)據(jù)最常用的格式,但是在 Swift4.0 之前,大家都是用一些第三方的開源庫來對 JSON 格式進行解析。

          終于, Apple 在 Swift4.0 的 Foundtion 模塊中添加了對 JSON 解析的原生支持,它的功能強大而且易于使用,接下來就讓我?guī)Т蠹?了解下在 swift 里如何來對你的數(shù)據(jù)進行 encoding 和 decoding 吧!

          基礎知識介紹

          在 swift 里要對 JSON 進行處理的話,首先需要了解的概念就是:Codable, Codable 其實它不是一個協(xié)議,而是另外倆個協(xié)議的組合:Decodable 和 Encodable,它的源碼如下所示:

          public typealias Codable = Decodable & Encodable

          所以聰明的你一定可以猜到,只要數(shù)據(jù)模型遵行了 Codable 協(xié)議,那么就可以方便的進行 JSON 和數(shù)據(jù)模型的相互轉(zhuǎn)換了。

          在 Swift4.0 中,Apple 提供了 JSONEncoder 和 JSONDecoder 倆對象來處理 JSON 的編碼和解碼,核心代碼如下:

          let encoder = JSONEncoder()
          let decoder = JSONDecoder()

          相關的概念已介紹完畢,你準備好迎接挑戰(zhàn)了嗎?

          image

          JSON 轉(zhuǎn)數(shù)據(jù)模型

          TASK 1:簡單的數(shù)據(jù)結(jié)構(gòu)

          如果你的 JSON 結(jié)構(gòu)和你使用的數(shù)據(jù)模型結(jié)構(gòu)一致的話,那么解析過程將會非常簡單,請看下面內(nèi)容:

          下面給出的是一個歌曲的 JSON 數(shù)據(jù),我現(xiàn)在要將其轉(zhuǎn)換為 SongModel。

          let song = """
                  {
                      "singer": "The Chainsmokers",
                      "name": "Something Just Like This",
                  }
              """

          SongModel

          /// SongModel模型,遵循 Codable 協(xié)議
          struct SongModelCodable {
              var singer: String?
              var name: String?
          }

          轉(zhuǎn)換過程如下

          if let jsonData = song.data(using: String.Encoding.utf8) {
              if let sSong = tryJSONDecoder().decode(SongModel.self, from: jsonData) {
                  dump(sSong)
              }
          }

          輸出結(jié)果如下

          JSONDecoderDemo.SongModel
            ? singer: Optional("The Chainsmokers")
              - some: "The Chainsmokers"
            ? name: Optional("Something Just Like This")
              - some: "Something Just Like This"

          這樣就完成了解析,是不是很簡單!

          NOTE:在數(shù)據(jù)模型的成員變量中,基本數(shù)據(jù)類型如:String、Int、Float等都已經(jīng)實現(xiàn)了 Codable 協(xié)議,因此如果你的數(shù)據(jù)類型只包含這些基本數(shù)據(jù)類型的屬性,只需要在類型聲明中加上 Codable 協(xié)議就可以了,不需要寫任何實際實現(xiàn)的代碼。

          TASK 2: 解析數(shù)組

          假如這是我們收到的一張專輯 Album 的 JSON 數(shù)據(jù),現(xiàn)在要把它轉(zhuǎn)化成 AlbumModel 數(shù)據(jù)模型。

          let album = """
                  {
                      "singer": "The Chainsmokers",
                      "name": "Something Just Like This",
                      "songs":[
                          "Something Just Like This",
                          "Closer",
                          "Young",
                          "All We Know"
                      ]
                  }
              """

          AlbumModel

          struct AlbumModelCodable {
              var singer: String?
              var name: String?
              var songs: [String]?
          }

          轉(zhuǎn)換過程如下

          if let jsonData = album.data(using: String.Encoding.utf8) {
              if let sSong = tryJSONDecoder().decode(AlbumModel.self, from: jsonData) {
                  dump(sSong)
              }
          }

          輸出結(jié)果為

          JSONDecoderDemo.AlbumModel
            ? singer: Optional("The Chainsmokers")
              - some: "The Chainsmokers"
            ? name: Optional("Something Just Like This")
              - some: "Something Just Like This"
            ? songs: Optional(["Something Just Like This""Closer""Young""All We Know"])
              ? some: 4 elements
                - "Something Just Like This"
                - "Closer"
                - "Young"
                - "All We Know"

          和上面的轉(zhuǎn)換如出一轍,想必你現(xiàn)在心里已經(jīng)在默默的嘀咕:這么簡單還用你講?

          image

          那接下來就請準備迎接新的挑戰(zhàn)把!

          TASK 3:結(jié)構(gòu)不一致

          上面所演示的 JSON 數(shù)據(jù)格式都是與數(shù)據(jù)模型里的成員變量一一對應的,但是,在實際開發(fā)中,你會經(jīng)常遇到數(shù)據(jù)源的格式和數(shù)據(jù)模型結(jié)構(gòu) 不一致的情況,很多情況下可能是服務端與客戶端沒有統(tǒng)一好接口的格式,然后各自就開始開發(fā),到需要進行調(diào)試的時候,客戶端一收到消息,就懵逼了:

          image

          NOTE: 所以在這里我非常建議大家在做功能開發(fā)之前一定要先把接口文檔定義好,定義好,定義好,重要的事情講三遍。

          這樣服務端和客戶端之間定義的數(shù)據(jù)格式就存在了差異,無論怎樣當然總有一方需要作出讓步來做到兼容,那么當客戶端想要做兼容時,該怎么處理呢!我們先來看個例子:

          例如服務端返回的數(shù)據(jù)為:

          let album = """
                  {
                      "singer": "The Chainsmokers",
                      "name": "Something Just Like This",
                      "songList":[
                          "Something Just Like This",
                          "Closer",
                          "Young",
                          "All We Know"
                      ]
                  }
              """

          可以看到,原來的 songs 換成了 songList,我們執(zhí)行下原先的代碼,看下輸出:

          JSONDecoderDemo.AlbumModel
            ? singer: Optional("The Chainsmokers")
              - some: "The Chainsmokers"
            ? name: Optional("Something Just Like This")
              - some: "Something Just Like This"
            - songs: nil

          發(fā)現(xiàn) songs 字段變成了 nil, 這個解析就失敗了,那如何做到不修改我之前定義的數(shù)據(jù)模型的成員變量,來做到兼容呢!這時候就需要用到 CodingKey 協(xié)議了, 借助 CodingKey 可以用來映射數(shù)據(jù)模型的成員變量,首先在數(shù)據(jù)模型中添加一個特殊的枚舉類型:

          private enum CodingKeysStringCodingKey

          添加完后的數(shù)據(jù)模型代碼如下:

          struct AlbumModelCodable {
              var singer: String?
              var name: String?
              var songs: [String]?
              
              enum CodingKeysStringCodingKey {
                  case singer = "singer"
                  case name = "name"
                  case songs = "songList"
              }
          }

          輸出結(jié)果為

          JSONDecoderDemo.AlbumModel
            ? singer: Optional("The Chainsmokers")
              - some: "The Chainsmokers"
            ? name: Optional("Something Just Like This")
              - some: "Something Just Like This"
            ? songs: Optional(["Something Just Like This""Closer""Young""All We Know"])
              ? some: 4 elements
                - "Something Just Like This"
                - "Closer"
                - "Young"
                - "All We Know"

          這樣,我們是不是就可以正常解析 JSON 數(shù)據(jù)了,是不是很強大。

          接下來再增加一個難度!

          當給你的唱片的 JSON 結(jié)構(gòu)是這樣的,你該怎么解析呢!

          let album = """
                  {
                      "singer": "The Chainsmokers",
                      "name": "Something Just Like This",
                      "songs": "Something Just Like This"
                  }
              """

          根據(jù)上面給出的例子,你會發(fā)現(xiàn)它依然與你的數(shù)據(jù)模型不匹配,原來的 songs 字段不是數(shù)組格式了,那如何才能正常的解析到數(shù)據(jù)模型上去呢,這時候就需要我們自己來實現(xiàn)編碼解碼的邏輯了。

          首先在 AlbumModel 中加入以下代碼:

          struct AlbumModelCodable {
              var singer: String?
              var name: String?
              var songs: [String]?

              // 1
              enum CodingKeysStringCodingKey {
                  case singer = "singer"
                  case name = "name"
                  case songs = "songs"
              }
              
              // 解碼: JSON 轉(zhuǎn) Model
              init(from decoder: Decoderthrows {
               // 2
                  let container = try decoder.container(keyedBy: CodingKeys.self)
                  // 3
                  singer = try container.decode(String.self, forKey: .singer)
                  name = try container.decode(String.self, forKey: .name)
                  let ss = try container.decode(String.self, forKey: .songs)
                  songs = [ss]
              }
              
              // 編碼: Model 轉(zhuǎn) JSON
              func encode(to encoder: Encoder) throws {
               // 4
                  var container = encoder.container(keyedBy: CodingKeys.self)
                  try container.encode(singer, forKey: .singer)
                  try container.encode(name, forKey: .name)
                  try container.encode(songs, forKey: .songs)
              }
          }

          解釋如下

          1. 創(chuàng)建 CodingKeys 枚舉,用于映射 JSON 字段。
          2. 創(chuàng)建一個解碼器容器,來存儲 JSON 里的屬性。
          3. 使用適當?shù)念愋秃途幋a鍵從容器中提取歌手和專輯名和歌單,由于歌單是數(shù)組類型的,所以需要將提取到的歌轉(zhuǎn)換成數(shù)組。
          4. 創(chuàng)建 KeyedEncodingContainer 容器來對數(shù)據(jù)模型里的屬性進行編碼。

          轉(zhuǎn)換過程如下

          if let jsonData = album.data(using: String.Encoding.utf8) {
              if let aAlbum = tryJSONDecoder().decode(AlbumModel.self, from: jsonData) {
                  dump(aAlbum)
              }
          }

          結(jié)果如下

          JSONDecoderDemo.AlbumModel
            ? singer: Optional("The Chainsmokers")
              - some: "The Chainsmokers"
            ? name: Optional("Something Just Like This")
              - some: "Something Just Like This"
            ? songs: Optional(["Something Just Like This"])
              ? some: 1 element
                - "Something Just Like This"

          可以看到通過上面的代碼,已經(jīng)可以將 JSON 中原先的 String 轉(zhuǎn)換成數(shù)據(jù)模型中的數(shù)組類型了。

          注意:如果需要借助 CodingKeys 解決字段不一致的情況,即使其他的屬性不需要映射,也必須將其包含在枚舉中,譬如:singer, name,否則會報錯。

          TASK 4:復雜的嵌套

          除了處理簡單的數(shù)據(jù)模型,Codable 還可以處理復雜的嵌套數(shù)據(jù)模型,首先解釋下什么是嵌套數(shù)據(jù)模型:

          譬如我有個專門處理專輯的數(shù)據(jù)模型叫 AlbumModel,它里面內(nèi)嵌了 SongModel 的屬性,這就是嵌套。這里必須要說明的就是嵌套的數(shù)據(jù)模型以及嵌套的子模型都必須遵循 Codable 協(xié)議,下面我們舉個嵌套的數(shù)據(jù)模型的例子來說明一下:

          /// 專輯模型
          struct AlbumModelCodable {
              // 專輯名
              var albumName: String?
              // 發(fā)布時間
              var releaseTime: String?
              // 歌單(嵌套)
              var songs: [SongModel]?
          }

          /// 歌曲模型
          struct SongModelCodable {
              // 歌手(嵌套)
              var singer: SingerModel?
              // 歌曲
              var name: String?
          }

          /// 歌手模型
          struct SingerModelCodable {
              // 姓名
              var name: String?
              // 年齡
              var age: Int?
          }

          JSON 數(shù)據(jù)結(jié)構(gòu)

              let album = """
                  {
                      "albumName": "Something Just Like This",
                      "releaseTime": "2017-02-22",
                      "songs":[
                          {
                              "singer": {
                                  "name":"The Chainsmokers",
                                  "age": 30
                              },
                              "name": "Something Just Like This"
                          },
                          {
                              "singer": {
                                  "name":"The Chainsmokers",
                                  "age": 30
                              },
                              "name": "Closer"
                          },
                          {
                              "singer": {
                                  "name":"The Chainsmokers",
                                  "age": 30
                              },
                              "name": "Young"
                          },
                          {
                              "singer": {
                                  "name":"The Chainsmokers",
                                  "age": 30
                              },
                              "name": "All We Know"
                          }
                      ]
                  }
              """

          轉(zhuǎn)換過程如下

          if let jsonData = album.data(using: String.Encoding.utf8) {
              if let aAlbum = tryJSONDecoder().decode(AlbumModel.self, from: jsonData) {
                  dump(aAlbum)
              }
          }

          輸出結(jié)果為

          JSONDecoderDemo.AlbumModel
            ? albumName: Optional("Something Just Like This")
              - some: "Something Just Like This"
            ? releaseTime: Optional("2017-02-22")
              - some: "2017-02-22"
            ? songs: Optional([JSONDecoderDemo.SongModel(singer: Optional(JSONDecoderDemo.SingerModel(name: Optional("The Chainsmokers"), age: Optional(30))), name: Optional("Something Just Like This")), JSONDecoderDemo.SongModel(singer: Optional(JSONDecoderDemo.SingerModel(name: Optional("The Chainsmokers"), age: Optional(30))), name: Optional("Closer")), JSONDecoderDemo.SongModel(singer: Optional(JSONDecoderDemo.SingerModel(name: Optional("The Chainsmokers"), age: Optional(30))), name: Optional("Young")), JSONDecoderDemo.SongModel(singer: Optional(JSONDecoderDemo.SingerModel(name: Optional("The Chainsmokers"), age: Optional(30))), name: Optional("All We Know"))])
              ? some: 4 elements
                ? JSONDecoderDemo.SongModel
                  ? singer: Optional(JSONDecoderDemo.SingerModel(name: Optional("The Chainsmokers"), age: Optional(30)))
                    ? some: JSONDecoderDemo.SingerModel
                      ? name: Optional("The Chainsmokers")
                        - some: "The Chainsmokers"
                      ? age: Optional(30)
                        - some: 30
                  ? name: Optional("Something Just Like This")
                    - some: "Something Just Like This"
                ? JSONDecoderDemo.SongModel
                  ? singer: Optional(JSONDecoderDemo.SingerModel(name: Optional("The Chainsmokers"), age: Optional(30)))
                    ? some: JSONDecoderDemo.SingerModel
                      ? name: Optional("The Chainsmokers")
                        - some: "The Chainsmokers"
                      ? age: Optional(30)
                        - some: 30
                  ? name: Optional("Closer")
                    - some: "Closer"
                ? JSONDecoderDemo.SongModel
                  ? singer: Optional(JSONDecoderDemo.SingerModel(name: Optional("The Chainsmokers"), age: Optional(30)))
                    ? some: JSONDecoderDemo.SingerModel
                      ? name: Optional("The Chainsmokers")
                        - some: "The Chainsmokers"
                      ? age: Optional(30)
                        - some: 30
                  ? name: Optional("Young")
                    - some: "Young"
                ? JSONDecoderDemo.SongModel
                  ? singer: Optional(JSONDecoderDemo.SingerModel(name: Optional("The Chainsmokers"), age: Optional(30)))
                    ? some: JSONDecoderDemo.SingerModel
                      ? name: Optional("The Chainsmokers")
                        - some: "The Chainsmokers"
                      ? age: Optional(30)
                        - some: 30
                  ? name: Optional("All We Know")
                    - some: "All We Know"

          這樣這個嵌套就被解決了,接下來再挑戰(zhàn)一個難度更大的,請看代碼:

          let album = """
                  {
                      "albumName": "Something Just Like This",
                      "releaseTime": "2017-02-22",
                      "songs": {
                          "favorite":[
                              {
                                  "singer": {
                                      "name":"The Chainsmokers",
                                      "age": 30
                                  },
                                  "name": "Something Just Like This"
                              },
                              {
                                  "singer": {
                                      "name":"The Chainsmokers",
                                      "age": 30
                                  },
                                  "name": "Closer"
                              },
                              {
                                  "singer": {
                                      "name":"The Chainsmokers",
                                      "age": 30
                                  },
                                  "name": "Young"
                              },
                              {
                                  "singer": {
                                      "name":"The Chainsmokers",
                                      "age": 30
                                  },
                                  "name": "All We Know"
                              }
                          ]
                      }
                  }
              """

          可以看到,在歌單 Songs 中又嵌套了一個 favorite 字段,這個 JSON 結(jié)構(gòu)相比 AlbumModel 這個數(shù)據(jù)模型又加深了一層,那該如何解析呢!

          image

          這里我們就要用到 nestedContainer 來處理這種嵌套,首先在 AlbumModel 加入如下代碼:

          /// 專輯模型
          struct AlbumModelCodable {
              // 專輯名
              var albumName: String?
              // 發(fā)布時間
              var releaseTime: String?
              // 歌單
              var songs: [SongModel]?
              
              // 1
              enum CodingKeysStringCodingKey {
                  case albumName, releaseTime, songs
              }
              // 2
              enum favoriteKeysCodingKey {
                  case favorite
              }

              // 解碼: JSON 轉(zhuǎn) Model
              init(from decoder: Decoderthrows {
                  // 3
                  let container = try decoder.container(keyedBy: CodingKeys.self)
                  albumName = try container.decode(String.self, forKey: .albumName)
                  releaseTime = try container.decode(String.self, forKey: .releaseTime)
                  // 4
                  let favoriteContainer = try container.nestedContainer(keyedBy: favoriteKeys.self, forKey: .songs)
                  songs = try favoriteContainer.decode([SongModel].self, forKey: .favorite)
              }

              // 編碼: Model 轉(zhuǎn) JSON
              func encode(to encoder: Encoder) throws {
                  // 5
                  var container = encoder.container(keyedBy: CodingKeys.self)
                  try container.encode(albumName, forKey: .albumName)
                  try container.encode(releaseTime, forKey: .releaseTime)
                  // 6
                  var favoriteContainer = container.nestedContainer(keyedBy: favoriteKeys.self, forKey: .songs)
                  try favoriteContainer.encode(songs, forKey: .favorite)
              }
          }
          /// 歌曲模型
          struct SongModelCodable {
              // 歌手
              var singer: SingerModel?
              // 歌曲
              var name: String?
          }

          /// 歌手模型
          struct SingerModelCodable {
              // 姓名
              var name: String?
              // 年齡
              var age: Int?
          }

          解析如下

          1. 首先創(chuàng)建最頂層的 CodingKeys
          2. 創(chuàng)建嵌套層的 CodingKeys
          3. 創(chuàng)建頂層 CodingKeys 對應的容器,并對其解碼
          4. 創(chuàng)建嵌套層的容器,并對 favorite 解碼
          5. 創(chuàng)建編碼容器,并對 albumName 和 releaseTime 編碼
          6. 獲取嵌套容器,并對 favorite 編碼

          轉(zhuǎn)換過程

          if let jsonData = album.data(using: String.Encoding.utf8) {
              if let aAlbum = tryJSONDecoder().decode(AlbumModel.self, from: jsonData) {
                  dump(aAlbum)
              }
          }

          輸出如下

          JSONDecoderDemo.AlbumModel
            ? albumName: Optional("Something Just Like This")
              - some: "Something Just Like This"
            ? releaseTime: Optional("2017-02-22")
              - some: "2017-02-22"
            ? songs: Optional([JSONDecoderDemo.SongModel(singer: Optional(JSONDecoderDemo.SingerModel(name: Optional("The Chainsmokers"), age: Optional(30))), name: Optional("Something Just Like This")), JSONDecoderDemo.SongModel(singer: Optional(JSONDecoderDemo.SingerModel(name: Optional("The Chainsmokers"), age: Optional(30))), name: Optional("Closer")), JSONDecoderDemo.SongModel(singer: Optional(JSONDecoderDemo.SingerModel(name: Optional("The Chainsmokers"), age: Optional(30))), name: Optional("Young")), JSONDecoderDemo.SongModel(singer: Optional(JSONDecoderDemo.SingerModel(name: Optional("The Chainsmokers"), age: Optional(30))), name: Optional("All We Know"))])
              ? some: 4 elements
                ? JSONDecoderDemo.SongModel
                  ? singer: Optional(JSONDecoderDemo.SingerModel(name: Optional("The Chainsmokers"), age: Optional(30)))
                    ? some: JSONDecoderDemo.SingerModel
                      ? name: Optional("The Chainsmokers")
                        - some: "The Chainsmokers"
                      ? age: Optional(30)
                        - some: 30
                  ? name: Optional("Something Just Like This")
                    - some: "Something Just Like This"
                ? JSONDecoderDemo.SongModel
                  ? singer: Optional(JSONDecoderDemo.SingerModel(name: Optional("The Chainsmokers"), age: Optional(30)))
                    ? some: JSONDecoderDemo.SingerModel
                      ? name: Optional("The Chainsmokers")
                        - some: "The Chainsmokers"
                      ? age: Optional(30)
                        - some: 30
                  ? name: Optional("Closer")
                    - some: "Closer"
                ? JSONDecoderDemo.SongModel
                  ? singer: Optional(JSONDecoderDemo.SingerModel(name: Optional("The Chainsmokers"), age: Optional(30)))
                    ? some: JSONDecoderDemo.SingerModel
                      ? name: Optional("The Chainsmokers")
                        - some: "The Chainsmokers"
                      ? age: Optional(30)
                        - some: 30
                  ? name: Optional("Young")
                    - some: "Young"
                ? JSONDecoderDemo.SongModel
                  ? singer: Optional(JSONDecoderDemo.SingerModel(name: Optional("The Chainsmokers"), age: Optional(30)))
                    ? some: JSONDecoderDemo.SingerModel
                      ? name: Optional("The Chainsmokers")
                        - some: "The Chainsmokers"
                      ? age: Optional(30)
                        - some: 30
                  ? name: Optional("All We Know")
                    - some: "All We Know"

          挑戰(zhàn)成功,看到這里是不是已經(jīng)有點暈了,說實話其實我自己也不知道我在表達啥,我也暈了,哈哈!

          image

          Task 6:處理派生類

          下面我們來看下一個特殊的數(shù)據(jù)模型結(jié)構(gòu),它應該怎么去轉(zhuǎn)換呢!

          當一個類遵循了 Codable 協(xié)議,那么它自身是可以很方便的使用 JSONEncoder 和 JSONDecoder 來 JSON 化和反 JSON 化的,但是如果有別的類繼承了它,那么對該子類的 JSON 化和反 JSON 化就不是那么方便了。

          首先來看個例子,SongMusic 的子類:

          class MusicCodable {
              var kind: String?
          }

          class SongMusic {
              var name: String?
          }

          JSON 數(shù)據(jù)為:

          let jsonString = """
                  {
                      "kind": "popular",
                      "name": "Something Just Like This"
                  }
              """

          數(shù)據(jù)解析

          if let jsonData = jsonString.data(using: String.Encoding.utf8) {
              if let song = tryJSONDecoder().decode(Song.self, from: jsonData) {
                  dump(song)
              }
          }

          結(jié)果

          JSONDecoderDemo.Song #0
            ? superJSONDecoderDemo.Music
              ? kind: Optional("popular")
                - some: "popular"
            - name: nil

          通過上面的結(jié)果發(fā)現(xiàn),Song 類的實例只解析出了父類中的 kind 字段,而自己的 name 未能解析,這說明 Codable 在繼承中是無效的,當你在派生類中聲明遵循該協(xié)議時,會報如下錯誤:

          Redundant conformance of 'Song' to protocol 'Decodable'
          Redundant conformance of 'Song' to protocol 'Encodable'

          那如何才能解決這個問題呢!

          這時候,就需要我們自行實現(xiàn) Codable 協(xié)議了,代碼如下:

          class SongMusic {
              var name: String?
              
              enum CodingKeysStringCodingKey {
                  case type
                  case name
              }
              
              init(type: String, name songName:String) {
                  self.name = songName
                  super.init(type: type)
              }
              
              required init(from decoder: Decoderthrows {
                  try super.init(from: decoder)
                  let container = try decoder.container(keyedBy: CodingKeys.self)
                  type = try container.decode(String.self, forKey: .type)
                  name = try container.decode(String.self, forKey: .name)
              }
              
              override func encode(to encoder: Encoder) throws {
                  var container = encoder.container(keyedBy: CodingKeys.self)
                  try container.encode(type, forKey: .type)
                  try container.encode(name, forKey: .name)
              }
          }

          轉(zhuǎn)換結(jié)果

          JSONDecoderDemo.Song #0
            ? superJSONDecoderDemo.Music
              ? type: Optional("popular")
                - some: "popular"
            ? name: Optional("Something Just Like This")
              - some: "Something Just Like This"

          通過上面的結(jié)果顯示,我已經(jīng)成功將 JSON 轉(zhuǎn)成了相應的數(shù)據(jù)模型,那么對派生類的處理,我們只需要參考上面的代碼,自行實現(xiàn) Codable 協(xié)議,就可以避免上述的錯誤。

          數(shù)據(jù)模型轉(zhuǎn) JSON

          當實現(xiàn) Codable 協(xié)議的某個對象想要轉(zhuǎn)為 JSON 時,則可以借助 JSONEncoder 編碼器來實現(xiàn)。

          這個轉(zhuǎn)換相對來說就比較簡單了,這里就舉個簡單的例子吧!

          let song = Song(type: "popular", name: "Something Just Like This")

          if let jsonData = tryJSONEncoder().encode(song){
              if let jsonString = String.init(data: jsonData, encoding: String.Encoding.utf8){
                  print("jsonString:" + "\(jsonString)")
              }
          }

          輸出結(jié)果

          jsonString:{"type":"popular","name":"Something Just Like This"}

          數(shù)據(jù)模型轉(zhuǎn) JSON 就完成了,So Easy

          image

          結(jié)語

          到這里本篇文章就結(jié)束了,首先非常感謝大家能耐著性子看到這里,說實話我在準備這篇文章的時候也有點痛苦,越寫越無聊,時常在寫的過程中腦子一直在想:這么無聊的內(nèi)容連我自己都寫不下去了,會有讀者愿意看嗎?但是開弓沒有回頭箭,畢竟我也花了幾天時間準備了素材,所以還是耐著寂寞寫完了,內(nèi)容過于枯燥,希望大家別嫌棄。

          image



          推薦閱讀:


          優(yōu)雅的處理網(wǎng)絡數(shù)據(jù),你真的會嗎?不如看看這篇.

          UICollectionView 自定義布局!看這篇就夠了!



          點擊 關注我的公眾號

          如果你想要跟大家分享你的文章,歡迎投稿

          (*^▽^*)


          瀏覽 22
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚州精品天堂中文字幕 | 欧美一性一乱一交一视频 | 操逼视频黄片中国版的中国的 | 天天射大香蕉 | 亚州成人色影网站 |