iOS解析本地Json

  • Demo代码地址:FileParsingJson

1. 本地Json文件与运行效果

{
    "jsonData": [
        {
            "title": "水果",
            "items": [
                "苹果",
                "香蕉",
                "梨",
                "西瓜"
            ]
        },
        {
            "title": "汽车",
            "items": [
                "宝马",
                "奔驰",
                "本田",
                "起亚"
            ]
        },
        {
            "title": "省份",
            "items": [
                "北京",
                "天津",
                "河北"
            ]
        }
    ]
}

iOS解析本地Json_第1张图片

2. Json解析

2.1 数据结构

Json是key-value的键值对,根据Json中的内容设计相应的数据结构才能正确解析数据:变量名和key一致、变量类型和value类型一致

  1. 整个Json看作一个自定义结构体Result
  • key是"jsonData",value是另一个自定义结构体ResultItem的数组
  1. ResultItem结构体:
  • key是"title",value是具体种类、类型为String
  • key是"items",value是该种类具体内容、类型为String数组
  1. 两个结构体都要遵守Codable协议
  • Swift 4引入了Codable协议,与NSCoding协议不同的是:如果自定义的类中全都是基本数据类型、基本对象类型,它们都已经实现了Codable协议,那么这个自定义的类也默认实现了Codable,无需再实现编解码,只需要在自定义的类声明它遵守Codable协议即可
struct Result: Codable {
    let jsonData: [ResultItem]
}
struct ResultItem: Codable {
    let title: String
    let items: [String]
}

2.2 获取本地Json文件路径并转为URL

  • 通过mainBundle获取 json 文件路径,因为可能找不到路径,比如文件名、类型名参数写错或文件不存在,因此要用guard ... else处理读不到的情况
  • URL(fileURLWithPath:)方法将文件路径转为 url
guard let path = Bundle.main.path(forResource: "data",ofType: "json")
else{
    return
}
let url = URL(fileURLWithPath: path)

2.3 将URL内容读入NSData、再读入结构体

  • Data(contentsOf: url)JSONDecoder().decode()都可能失败throw异常,因此放在do{} catch{}中,并try
  • 上面两个方法任意一个执行出错,result就成了nil,因此声明为可选型
    iOS解析本地Json_第2张图片
    iOS解析本地Json_第3张图片
var result: Result?
do {
    let jsonData = try Data(contentsOf: url)
    result = try JSONDecoder().decode(Result.self, from: jsonData)
}
catch {
    print("Error:\(error)")
}

3. 创建Table View并读入数据

3.1 代码方式创建Table View

  • 设置Table View样式、cell复用identifier
  • {//代码体}(),匿名函数格式,小括号表示立即调用大括号中定义的函数体
let tableView:UITableView = {
    let table = UITableView(frame: .zero, style: .grouped)
    table.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
    return table
}()

3.2 设置Table View

override func viewDidLoad() {
    super.viewDidLoad()
    parseJson()
    //加入当前视图的子树图,并设置在父视图中的位置frame
    view.addSubview(tableView)
    tableView.frame = view.bounds
    //设置数据源和代理
    tableView.delegate = self
    tableView.dataSource = self
}

3.3 实现Table View的数据源方法

  1. section数,即ResultItem数组中的元素个数,resultnil时返回 0
func numberOfSections(in tableView: UITableView) -> Int {
    return result?.jsonData.count ?? 0
}
  1. section标题,ResultItemtitle
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return result?.jsonData[section].title
}
  1. 行数,ResultItemitems数组中的元素个数
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if let res = result {
        return res.jsonData[section].items.count
    }
    return 0
}
  1. 行内容,ResultItemitems数组中的值
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let contents =  result?.jsonData[indexPath.section].items[indexPath.row]
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
    cell.textLabel?.text = contents
    return cell
}

你可能感兴趣的:(iOS开发,json,ios)