第一次在 Swift 中使用 JSON,当我尝试使用我的模型解析文件时,出现此错误:
The given data was not valid JSON.
我认为问题在于我如何做我的模型。
我解析JSON的方式:
import SwiftUI
struct EmergencyView: View {
let emergency: [EmergencyNumberModel]
init() {
let url = Bundle.main.url(forResource: "emergency",
withExtension: "json")!
let data = try! Data(contentsOf: url)
emergency = try! JSONDecoder().decode([EmergencyNumberModel].self, from: data) //Error
}
var body: some View {
List(emergency, id: \.id) { emer in
if emer.Country != nil {
Label(emer.Country, systemImage: "quote.bubble")
.font(.headline)
} else{
Text(emer.Country)
}
}
navigationTitle("Emergency")
}
}
这是我使用的 JSON 的一小部分,“emergency.json”:
[
{
"Country": {
"Name": "Afghanistan",
"ISOCode": "AF",
"ISONumeric": "4"
},
"Ambulance": {
"All": [
"112"
]
},
"Fire": {
"All": [
"119"
]
},
"Police": {
"All": [
"119"
]
},
"Dispatch": {
"All": [
null
]
},
"Member_112": false,
"LocalOnly": true,
"Notes": false
},
.
.
.
]
这是我的模型,“EmergencyNumberModel.swift”:
struct EmergencyNumberModel: Codable, Identifiable {
var id = UUID()
let Country: String
let Ambulance: String
let Fire: String
let Police: String
let Dispatch: String
}
我的模型中是否需要其他变量来访问内部键或变量的数据类型错误?
解决方案
使用https://app.quicktype.io/生成 swift 结构,这是使用 json 数据的一种基本方法:
struct EmergencyView: View {
@State var emergencies: [EmergencyModel] = [] // <--- here
var body: some View {
List(emergencies) { emer in
if emer.country.name.isEmpty {
Text("no country name")
} else {
Label(emer.country.name, systemImage: "quote.bubble").font(.headline)
}
}
.onAppear {
if let emrgncy = loadData(from: "emergency") { // <--- here
emergencies = emrgncy
}
}
}
func loadData(from file: String) -> [EmergencyModel]? {
do {
if let filePath = Bundle.main.path(forResource: file, ofType: "json") {
let data = try Data(contentsOf: URL(fileURLWithPath: filePath))
let results = try JSONDecoder().decode([EmergencyModel].self, from: data)
return results
}
} catch {
print("----> error: \(error)") // <-- todo, deal with errors
}
return nil
}
}
struct EmergencyModel: Identifiable, Codable {
let id = UUID() // <--- here
let country: Country
let ambulance, fire, police: Ambulance
let dispatch: Dispatch
let member112, localOnly, notes: Bool
enum CodingKeys: String, CodingKey {
case country = "Country"
case ambulance = "Ambulance"
case fire = "Fire"
case police = "Police"
case dispatch = "Dispatch"
case member112 = "Member_112"
case localOnly = "LocalOnly"
case notes = "Notes"
}
}
struct Ambulance: Codable {
let all: [String]
enum CodingKeys: String, CodingKey {
case all = "All"
}
}
struct Country: Codable {
let name, isoCode, isoNumeric: String
enum CodingKeys: String, CodingKey {
case name = "Name"
case isoCode = "ISOCode"
case isoNumeric = "ISONumeric"
}
}
struct Dispatch: Codable {
let all: [JSONNull?]
enum CodingKeys: String, CodingKey {
case all = "All"
}
}
class JSONNull: Codable, Hashable {
public static func == (lhs: JSONNull, rhs: JSONNull) -> Bool {
return true
}
func hash(into hasher: inout Hasher) {
hasher.combine(0)
}
public init() {}
public required init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if !container.decodeNil() {
throw DecodingError.typeMismatch(JSONNull.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for JSONNull"))
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encodeNil()
}
}
精品教程推荐
加入我们一起学习SwiftUI
QQ:3365059189
SwiftUI技术交流QQ群:518696470
教程网站:www.openswiftui.com