我正在尝试解码这个名为
Menu.json
的 JSON
[
{
"day": "Monday",
"locationName": "Memorial Union Quad",
"coordinate": [38.54141, -121.74845],
"menu": {
"Penne Pasta w/ Bolognese" : ["🌾","🐷"],
"Penne Pasta w/ Roasted Mushrooms" : ["🌾","V"]
}
},
{
"day": "Tuesday",
"locationName": "International Center",
"coordinate": [38.54540, -121.75494],
"menu": {
"Beef & Lamb Gyro" : ["🌾","🫛", "🥛"],
"Edamame Hummus w/ Veggies" : ["🫛","🥛", "SE", "VE"]
}
},
{
"day": "Wednesday",
"locationName": "Storer Hall",
"coordinate": [38.54114, -121.75461],
"menu": {
"Seafood Salad Tostada" : ["🥚","🦐", "🫛", "🐟"],
"Southwest Black Bean Tostada" : ["V"]
}
},
{
"day": "Thursday",
"locationName": "Orchard Park",
"coordinate": [38.544828, -121.765170],
"menu": {
"Teriyaki Beef w/ Stir Fry Noodles" : ["🌾","🫛", "SE"],
"Teriyaki Tofu w/ Veggie Stir Fry" : ["🌾","🫛", "SE","V"]
}
},
{
"day": "Friday",
"locationName": "Memorial Union Quad",
"coordinate": [38.54141, -121.74845],
"menu": {
"Soy Ciltrano Lime Chicken" : ["🌾","🫛"],
"Southwest Tofu" : ["🫛","V"]
}
}
]
这就是我在 Swift 中建模数据的方式:
import Foundation
import OrderedCollections
struct Menu : Codable, Hashable {
var id: UUID { UUID() }
let day: String
let locationName: String
let coordinate: [Double]
let menu: OrderedDictionary<String, [String]>
func getTodaysLocation(_ today: String)-> String{
if today == day{
return locationName
}
return ""
}
}
这就是我解码数据的方式:
import Foundation
extension Bundle {
func decode(_ file: String) -> [Menu] {
guard let url = self.url(forResource: file, withExtension: nil) else {
fatalError("Failed to locate \(file) in bundle.")
}
guard let data = try? Data(contentsOf: url) else {
fatalError("Failed to load \(file) from bundle.")
}
let decoder = JSONDecoder()
do {
return try decoder.decode([Menu].self, from: data)
} catch DecodingError.keyNotFound(let key, let context) {
fatalError("Failed to decode \(file) from bundle due to missing key '\(key.stringValue)' – \(context.debugDescription)")
} catch DecodingError.typeMismatch(_, let context) {
fatalError("Failed to decode \(file) from bundle due to type mismatch – \(context.debugDescription)")
} catch DecodingError.valueNotFound(let type, let context) {
fatalError("Failed to decode \(file) from bundle due to missing \(type) value – \(context.debugDescription)")
} catch DecodingError.dataCorrupted(_) {
fatalError("Failed to decode \(file) from bundle because it appears to be invalid JSON.")
} catch {
fatalError("Failed to decode \(file) from bundle: \(error.localizedDescription)")
}
}
}
但我收到以下错误:“由于类型不匹配,无法从捆绑包中解码 Menu.json – 预期解码数组
我对数据的建模是否正确?还是Bundle中的解码功能有问题?
我尝试修改数据建模方式,但我刚接触 JSON,所以我不完全确定问题是否在于我在 Swift 中建模 JSON 的方式。
OrderedCollection
的文档描述了这种类型所需的结构:
希望其内容在未加密的容器中被编码为交替键值对。OrderedDictionary
即如果你想使用
OrderedCollection
,你必须使用不同的JSON结构:
[
{
"day": "Monday",
"locationName": "Memorial Union Quad",
"coordinate": [38.54141, -121.74845],
"menu": [
"Penne Pasta w/ Bolognese",
["🌾","🐷"],
"Penne Pasta w/ Roasted Mushrooms",
["🌾","V"]
]
}
]
一般来说,如果项目的顺序很重要,则不应使用 JSON 对象作为“菜单”,而应使用数组。
有多种不同的方式来构造或解码数据。这是一种替代方案:
struct Menu: Codable, Hashable {
var id: UUID { UUID() }
let day: String
let locationName: String
let coordinate: [Double]
let menu: [MenuItem]
}
struct MenuItem: Codable, Hashable {
let description: String
let ingredients: [String]
}
JSON 具有以下结构:
[
{
"day": "Monday",
"locationName": "Memorial Union Quad",
"coordinate": [38.54141, -121.74845],
"menu": [
{
"description": "Penne Pasta w/ Bolognese",
"ingredients": ["🌾","🐷"]
},
{
"description": "Penne Pasta w/ Roasted Mushrooms",
"ingredients": ["🌾","V"]
}
]
}
]