JSONEncode JSONDecode

序列化模型到 JSON,和反序列化 JSON 到模型,在 Swift4 之前一直都比较麻烦,所以像一些第三方库就非常的流行,比如 SwiftJSON,HandyJSON 等,例如我们在 Swift3 下,只能使用 JSONSerialization 这个类,进行序列化和反序列化,但是有一个明显的问题没办法解决。

JSONSerialization 无法将 JSON 直接反序列化成模型,只能反序列成字典,数组,String 这种系统内置类型。 也就是为什么,HandyJson 这种第三方库会非常的流行。

例如:

let json = try? JSONSerialization.jsonObject(with: data, options: []) 
if  let recipe = json as? [String: Any]
{ if  let yield = recipe["yield"] as? Int 
  { recipeObject.yield = yield }
 }

JSONEncode JSONDecode 的出现

在 Swift4 出来之后,系统提供了 Codable 协议 ,JSONEncode,JSONDecode 类型, 解决了反序列化成模型的问题。

下面我们举几个使用例子

1.模型转换成 JSON

例如:

struct User: Codable {
    var name: String
    var age: String
    var gender: String
}

let user = User(name: "Henry", age: "21", gender: "male")
let encoder = JSONEncoder()
let data = try! encoder.encode(user)
let str = String(data: data, encoding: .utf8)
print("str:\(str)")

// `str:Optional("{\"name\":\"Henry\",\"age\":\"21\",\"gender\":\"male\"}")`

2.JSON 转换成模型

例如:

let userJSONStr = """
{"name":"John","age":"14","gender":"male"}
"""

struct User: Codable {
    var name: String
    var age: String
    var gender: String
}

let decoder = JSONDecoder()
let user = try! decoder.decode(User.self, from: userJSONStr.data(using: .utf8)!)
print("[STRUCT] user.name:\(user.name)")


// [STRUCT] user.name:John
// [CLASS] user.name:John

JSON 反序列化成 Model 的规则

我举了两个例子,图解什么样的数据结构可以映射成功。

例子 1: WechatIMG1126.png

例子 2: 可以看到,很 cool 使用枚举类型来嵌入我们的模型,但是在验证中得出,只要服务器下发的字段,无法匹配上这个枚举,就会导致反序列化失败,整个 Model 无法被反序列化,所以这个还是慎用,如果是你和服务器是严格约定好的,那么没有任何问题。

WechatIMG1127.png

通过上图的例子,你可以清楚看到,JSONDecode 是严格按照数据类型来反序列化的,也就是,比如你和服务器订好了,这个字段 A 的类型就是一个 String,但是某一天你改了类型,改成了 Int,那么不好意思,这个反序列化会失败,整个 Model 都不能被解析出来,但是比如服务器去掉了这个字段,我只需要把模型中的类型,换成可选类型,还是可以映射成功的。

最后 这篇文章只是一个最基础的讲解,反序列化的能与不能没,如果想要具体查看详细的使用,更多用法,可以去这里 https://www.raywenderlich.com/3418439-encoding-and-decoding-in-swift

最后更新于

这有帮助吗?