SwiftUI之解析JSON

1,932 阅读2分钟

这是我参与8月更文挑战的第11天,活动详情查看:8月更文挑战

一、应用场景

JSON因为其简洁直观的特性,在很多语言中都有广泛的使用,SwiftUI中也不例外。如果只是需要在项目中做一些数据或者配置的简单的初始化,不需要如数据库的增删改查操作的话,使用JSON文件并在项目启动中解析不失为一个好方式。

二、实战

1. 首先在项目Data目录下创建一个文件Test.json,保存有如下数据。

image.png

[
  {
    "id": 1,
    "name": "Tom",
    "age": 19,
    "sex": "男"
  },
  {
    "id": 2,
    "name": "Lily",
    "age": 22,
    "sex": "女"
  },
  {
    "id": 3,
    "name": "John",
    "age": 17,
    "sex": "男"
  },
  {
    "id": 4,
    "name": "Lucy",
    "age": 28,
    "sex": "女"
  }
]

2. 然后创建一个struct名字叫Person.swift

因为后续要从Json解析为Bean,所以要实现Decodable协议。同样,后续要对整个数组进行ForEach遍历,所以实现Identifiable

代码如下:

struct Person: Identifiable, Decodable {
    var id: Int
    var name: String
    var age: Int
    var sex: String
}

3. 最后开始解析JSON

这里需要分为四步:

    1. 首先,从项目目录中找到Test.json文件。
    1. 将改文件读入URL中。
    1. 使用Data解析URL
    1. 最后使用JSONDecoder解析json数据并将其转换为Person数组。
class PersonModel: ObservableObject{
    
    @Published var people: [Person] = []
     
    init() {
        let pathString = Bundle.main.path(forResource: "Test", ofType: "json")
        
        if let path = pathString {
            
            let url = URL(fileURLWithPath: path)
            
            do{
                
                let data = try Data(contentsOf: url)
                
                let decoder = JSONDecoder()
                
                DispatchQueue.main.async {
                    do {
                        self.people = try decoder.decode([Person].self, from: data)
                    } catch {
                        print("Decode Json Error")
                    }
                }
            }catch{
                print("Parse Data Error")
            }
            
        }
    }
}
  • pathStringOptional类型,所以要解包。
  • Data解析URLJSONDecoder解析json有可能抛出错误,所以要用try+do{}catch{}捕获异常。
  • 这里面用SwiftUIcombine框架,初始化数据后,在所有的页面中共享次数据
  • self.people = try decoder.decode([Person].self, from: data)会触发更新视图,知道数据都解析完,才会渲染UI视图,如果数据量特别大的情况下,会出现加载数据时白屏的情况。所以使用DispatchQueue.main.async异步的方式来实现。
  • 第一步的解析json文件,同样可以通过HTTP请求,从网络上加载。比如let url = URL(string: "https://xxxxxxxxxxxxxx.com/people")

4. View中加载初始化好的数据

如在ContentView中引用该数据。

struct ContentView: View {
    
    @EnvironmentObject var model: PersonModel
    
    var body: some View {
        List{
            ForEach(model.people){person in
                HStack(spacing: 20){
                    Text("id:\(person.id)")
                    Text("name:\(person.name)")
                    Text("age:\(person.age)")
                    Text("sex:\(person.sex)")
                }
            }
        }
    }
}

效果如下:

image.png