没有多好的文笔,也没有多大的智慧,网上搜索Decodable资料有多少我就不知道了,我只想要傻瓜式的,一句话调用,json转模型!
重要的事情说三遍(Decodable是苹果官方的 Swift4新特性,Decodable是苹果官方的 Swift4新特性,Decodable是苹果官方的 Swift4新特性)
假设你的json长成这样
{
status:1000,
message:“操作成功”,
data:{
test:"我是测试数据"
}
}
或者这样
{
status:1000,
message:“操作成功”,
data:{
Test:{
detail:"测试内的数据",
detailMessage:“我也是测试内的数据,
}
}
}
怎么办呢,别急,我们一步一步的来,虽然看起来写比较粗糙,实用就好,当然你有更好的写法记得告诉我一下,技术因分享而有价值!
第一步 新建DecodableModels.Swift
import Foundation
/// 只有状态值和提示信息的模型转化
struct ModelObjet: Decodable {
/// 状态值
var status:Int? = nil
/// 提示信息
var message:String? = nil
}
/// 转换成数组模型
struct ModelObjetT<T: Decodable>: Decodable {
/// 状态值
var status:Int? = nil
/// 提示信息
var message:String? = nil
/// 嵌套模型
var data:T? = nil
}
/// 转换成数组模型
struct ModelArrayT<T: Decodable>: Decodable {
/// 状态值
var status:Int? = nil
/// 提示信息
var message:String? = nil
/// 嵌套模型
var data:[T]? = nil
}
注: var status:Int? = nil 这种写法是因为Swift的类型推断会很慢,这样手动指定,会提高编译器运行效率!
第二步 写上两个分类
extension Data {
/// json data 转模型
/// 可以直接拿网络请求成功的response直接转换
func jsonDataMapModel<T: Decodable>(_ type: T.Type) -> T? {
let decoder = JSONDecoder()
do {
return try decoder.decode(T.self, from: self)
} catch {
print("解析失败\(self)")
return nil
}
}
}
extension String {
/// json字符串转模型
func jsonStringMapModel<T: Decodable>(_ type: T.Type) -> T? {
if let jsonData = self.data(using: .utf8) {
return jsonData.jsonDataMapModel(T.self)
}
print("解析失败\(self)")
return nil
}
}
第三步 搞事情
模拟创建一个json字符串
let jsonString = "{\"status\":1000,\"message\":\"操作成功\",\"data\":{\"test\":\"测试文字\"}}"
然后
创建一个Test模型
struct Test:Decodable {
var test:String?
}
我们就可以输出
let model = jsonString.jsonStringMapModel(ModelObjetT<Test>.self)
print(model?.message ?? "")
或者是这样
print(model?.data?.test ?? "")
开发过程中发现一个didSet无效的问题
class Test:Decodable {
var name: String?
/// 测试文字
var test:String?{
didSet{
name = test
}
}
}
// json字符串一键转模型
let jsonString = "{\"status\":1000,\"message\":\"操作成功\",\"data\":{\"test\":\"0.05\"}}"
let model = jsonString.jsonStringMapModel(ModelObjetT<Test>.self)
print(model?.data?.test ?? "test无值")
print(model?.data?.name ?? 0.00)
无情的打印结果
0.05
0.00
更改如下
class Test:Decodable {
lazy var name: Double? = { return Double(test ?? "0.00") ?? 0.00 * 100 }()
/// 测试文字
var test:String?
}
这下就杠杠的了
0.05
5.0
来波完整的,新建一个.playground粘贴进去即可
import UIKit
/// 只有状态值和提示信息的模型转化
struct ModelObjet: Decodable {
/// 状态值
var status:Int? = nil
/// 提示信息
var message:String? = nil
}
/// 转换成数组模型
struct ModelObjetT<T: Decodable>: Decodable {
/// 状态值
var status:Int? = nil
/// 提示信息
var message:String? = nil
/// 嵌套模型
var data:T? = nil
}
/// 转换成数组模型
struct ModelArrayT<T: Decodable>: Decodable {
/// 状态值
var status:Int? = nil
/// 提示信息
var message:String? = nil
/// 嵌套模型
var data:[T]? = nil
}
extension Data {
/// json data 转模型
/// 可以直接拿网络请求成功的response直接转换
func jsonDataMapModel<T: Decodable>(_ type: T.Type) -> T? {
let decoder = JSONDecoder()
do {
return try decoder.decode(T.self, from: self)
} catch {
print("解析失败\(self)")
return nil
}
}
}
extension String {
/// json字符串转模型
func jsonStringMapModel<T: Decodable>(_ type: T.Type) -> T? {
if let jsonData = self.data(using: .utf8) {
return jsonData.jsonDataMapModel(T.self)
}
print("解析失败\(self)")
return nil
}
}
class Test1:Decodable {
lazy var name: Double? = { return (Double(test ?? "0.00") ?? 0.00) * 100 }()
/// 测试文字
var test:String?
}
class Test2:Decodable {
lazy var name: String? = { return "我是test_name转换之后的\(test_name ?? "")" }()
/// 测试文字
var test_name:String?
var detial:[Detial]?
}
class Detial:Decodable {
var detial_name: String?
}
// json字符串一键转模型
func test1(){
let jsonString = "{\"status\":1000,\"message\":\"操作成功\",\"data\":{\"test\":\"0.05\"}}"
let model = jsonString.jsonStringMapModel(ModelObjetT<Test1>.self)
print(model?.data?.test ?? "test无值")
print(model?.data?.name ?? 0.00)
print("============华丽的分割线==============")
}
func test2(){
let jsonString = "{\"status\":1000,\"message\":\"操作成功\",\"data\":{\"test_name\":\"Decodable\",\"detial\":[{\"detial_name\":\"看吧嵌套毫无压力\"}]}}"
let model = jsonString.jsonStringMapModel(ModelObjetT<Test2>.self)
print(model?.data?.test_name ?? "test无值")
print(model?.data?.name ?? "name无值")
print(model?.data?.detial?.first?.detial_name ?? "detial_name无值")
}
test1()
test2()
好啦,今天就先扯到这,有什么不懂的可以加QQ群384089763我们一起探讨,咱们不见不散!
网友评论