代码
import Foundation
struct YZWJsonExtension {
//MARK: - decode
/// 解码入口。type传入AnyClass.self 。
public static func decode<T>(type: T.Type, object: Any?) throws -> T? where T : Decodable {
if let object = object, let data = YZWJsonExtension.decode(object: object) {
return YZWJsonExtension.decode(type: type, data: data)
}
return nil
}
/// 将object转成data
public static func decode(object: Any) -> Data? {
if let data = object as? Data {
return data
} else if let string = object as? String {
return string.data(using: .utf8)
}
return try? JSONSerialization.data(withJSONObject: object)
}
/// codable
private static func decode<T>(type: T.Type, data: Data) -> T? where T : Decodable {
do {
let object = try JSONDecoder().decode(type, from: data)
return object
} catch {
if let jsonStr = String(data: data, encoding: .utf8) {
print(jsonStr)
}
switch error {
case let DecodingError.typeMismatch(_, context):
print("数据类型错误:", context.codingPath, context.debugDescription, separator: "\n\n", terminator: "\n")
case let DecodingError.valueNotFound(_, context):
print("找不到value:", context, separator: "\n", terminator: "\n\n")
case let DecodingError.keyNotFound(_, context):
print("找不到Key:", context, separator: "\n", terminator: "\n\n")
case let DecodingError.dataCorrupted(context):
print("Json格式错误:", context, separator: "\n", terminator: "\n\n")
default:
print("Decode出现未知异常")
}
}
return nil
}
//MARK: - encode 编码
/// model, models -> type类型
public static func encodeJsonObject<T>(model: T) -> Any? where T : Encodable {
if let data = try? JSONEncoder().encode(model) {
return try? JSONSerialization.jsonObject(with: data)
}
return nil
}
/// model, models转成json data
public static func encodeData<T>(model: T) -> Data? where T: Encodable {
return try? JSONEncoder().encode(model)
}
}
使用Codable必要条件
要使用Codable需要满足:
- 对象为
struct
,class
类型,并继承Codable对象。 - 如果存储的属性有
enum
,struct
,class
类型,也必须继承Codable对象。
转换原理
使用Codable进行模型与字典、模型数组与字典数组的互转都是需要将对象转成Data
类型,通过Data
类型来进行转换。
Data
是一串Json(NSJSONWritingPrettyPrinted
)格式的字符串,使用UTF8
编码转成的Data
。
JsonString to Data
jsonString.data(using: .utf8)
Array or Dictionary to Data
JSONSerialization.data(withJSONObject: object)
Array or Model to Data
JSONEncoder().encode(model) // model 为Array<Model>或Model
Data to JsonString
String(data: data, encoding: .utf8)
Data to Array or Dictionary
JSONSerialization.jsonObject(with: data)
Data to Array or Model
JSONDecoder().decode([Model].self, from: data) // Array<Model> , [Model] 也可以写成 Array<Model>
JSONDecoder().decode(Model.self, from: data) // Model
CodingKeys(Json的key与语言的声明冲突)
enum CodingKeys: String, CodingKey {
case yourKey = "jsonKey"
}
以上代码是将Json中jsonKey
这个名称替换成yourKey
。这样就可以避免名称冲突。
只需将需要替换的Key进行设置,如果没有存在需要修改的Key,那么这个enum可以不写
。
报错
DecodingError.typeMismatch(_, context)
数据类型错误
DecodingError.valueNotFound(_, context)
找不到value,当这个Value在声明的时候没有定义成可选?
,那么如果value为空值
则会报这个错。
DecodingError.keyNotFound(_, context)
找不到Key,当这个Key在声明的时候没有定义成可选?
,那么Json中不包含这个Key
则会报这个错。
DecodingError.dataCorrupted(context)
Json格式错误