如何从 JSON 文件构建模型
Posted
技术标签:
【中文标题】如何从 JSON 文件构建模型【英文标题】:How to build a model from a JSON file 【发布时间】:2021-11-18 04:20:27 【问题描述】:这是我第一次在 Swift 中使用 JSON,当我尝试使用我的模型解析文件时,出现以下错误:
给定的数据不是有效的 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
我的模型中是否需要其他变量才能访问内部键或变量的数据类型错误?
【问题讨论】:
“构建”你的模型,将你的 json 复制并粘贴到quicktype.io 它会为你生成你的 swift 模型。请注意,在 View 的init()
中进行解码不是一个好主意。为此建立一个专门的模型/经理。也不要使用“!”在您的代码中。
关于的好建议。现在,您的 EmergencyNumberModel
与 JSON 不匹配——它需要进行重大更改才能正确解码(您可能应该使用 do/try/catch
来做——而不是 try!
)。 app.quicktype.io 将是解决此问题的最快方式。
如果您收到的错误是“给定的数据不是有效的 JSON”。那么问题不在于您的模型(至少,不是直接的问题),而在于您的 JSON。我建议使用像 JSONlint.com 这样的验证器来确保你的 JSON 是好的。
【参考方案1】:
使用https://app.quicktype.io/,生成快速结构, 这是使用 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()
【讨论】:
这并不能解决无效json的问题。以上是关于如何从 JSON 文件构建模型的主要内容,如果未能解决你的问题,请参考以下文章