JSON作为数据的一种存储格式,具有简洁,便于读写的优点。Swift内部就提供了对JSON格式数据进行解析的库,使用也比较简单,但也有些使用时需要注意的点。
以官网提供的landmark为例,解析landmarkData.json
,其数据如下
[
{
"name": "Turtle Rock",
"category": "Rivers",
"city": "Twentynine Palms",
"state": "California",
"id": 1001,
"isFeatured": true,
"isFavorite": true,
"park": "Joshua Tree National Park",
"coordinates": {
"longitude": -116.166868,
"latitude": 34.011286
},
"description": "...",
"imageName": "turtlerock"
},
{
"name": "Silver Salmon Creek",
"category": "Lakes",
"city": "Port Alsworth",
"state": "Alaska",
"id": 1002,
"isFeatured": false,
"isFavorite": false,
"park": "Lake Clark National Park and Preserve",
"coordinates": {
"longitude": -152.665167,
"latitude": 59.980167
},
"description": "...",
"imageName": "chilkoottrail"
},
......
{
"name": "Lake Umbagog",
"category": "Lakes",
"city": "Errol",
"state": "New Hampshire",
"id": 1012,
"isFeatured": false,
"isFavorite": false,
"park": "Umbagog National Wildlife Refuge",
"coordinates": {
"longitude": -71.056816,
"latitude": 44.747408
},
"description": "...",
"imageName": "umbagog"
}
]
构建数据对象
关键步骤就是构建一个与之相匹配的DataObject,注意属性名称(区分大小写)和类型均要与Json文件中相对应。以下是与landmarkData.json
相对应的DataObject
struct Landmark:Hashable,Codable,Identifiable{
var id:Int
var name:String
var park:String
var state:String
var description:String
private var imageName:String
//image为计算属性
var image:UIImage{
Image(imageName)
}
private var coordinates:Coordinates
struct Coordinates:Hashable,Codable{
var latitude:Double
var longitude:Double
}
var locationCoordinate:CLLocationCoordinate2D{
CLLocationCoordinate2D(latitude: coordinates.latitude, longitude: coordinates.longitude)
}
}
Json文件中的出现的Key不一定要全部在DataObject中声明,但是DataOject中除了计算属性外的属性均要在Json文件中出现(属性名称和类型有一个不匹配就会报错,无法解析)
解析JSON数据
加载Json文件并解析(要求数据对象遵循Codable
协议)
相关代码
func load<T:Decodable>(_ filename:String)->T{
let data:Data
guard let file = Bundle.main.url(forResource: filename, withExtension: nil)else{
fatalError("Couldn't find \(filename) in main bundle.")
}
do{
data = try Data(contentsOf: file)
}catch{
fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
}
do{
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
}catch{
fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}
}