这是我第一次在Codable / Decodable上拍摄,我想解码一个JSON。我试图访问"名称"和"描述"事件数组中的键。下面是JSON的片段 - 我在我的代码中收到此错误
"预计会解码字典,但会找到一个数组。"
"pagination": {
"page_number": 1,
"page_size": 50,
"continuation": "eyJwYWdlIjogMn0",
"has_more_items": true
},
"events": [
{
"name": {
"text": "Genesis Part 4",
"html": "Genesis Part 4"
},
"description": {
"text": "Wednesday, June 6-June 27, 2018\n12:00-2:15 PM, Eastern Time\n\u00a0\nCOED\n\u00a0\nBible Study Leader:\u00a0Nicki Cornett\n\u00a0\nContact:NickiCornett@gmail.com\n\u00a0\nGenesis Part 4 -\u00a0Wrestling with God - A Study on Isaac, Jacob, and Esau- Precept Workbook (NASB)\n\u00a0\nGod renews His covenant promise with Abraham through Isaac and Jacob.
以下是我如何进行解码 - (注意 - "说明"还没有到来,因为我在使用事件数组进行名称和解释时遇到了问题
struct Eventbrite: Decodable {
private enum CodingKeys : String, CodingKey { case events = "events", name = "name"}
let events: [String:[String]]
let name: [String:[String]]
}
URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let data = data else {return}
do {
let eventbriteData = try JSONDecoder().decode(Eventbrite.self, from: data)
print(eventbriteData.name)
答案 0 :(得分:2)
name
显然不在pagination
和events
的范围内(请注意{}
),并且是一个可以解码为[String:String]
的常规description
词典另一个结构。
对此进行解码(由于CodingKeys
不完整我将其删除了),您不需要struct Eventbrite: Decodable {
let events: [Event]
}
struct Event: Decodable {
let name: Name
// let description: [String:String]
}
struct Name : Decodable {
let text, html : String
}
:
private void promptFilmRating() {
Scanner filmScanner = new Scanner(System.in);
int filmRatingOutOfFive;
do{
System.out.println("Please enter your rating for the film:");
filmRatingOutOfFive = filmScanner.nextInt();
if(filmRatingOutOfFive > 5 || filmRatingOutOfFive < 1)
System.out.println("Your number is outside of the rating boundaries, enter a number between 1 and 5.");
}while(filmRatingOutOfFive > 5 || filmRatingOutOfFive < 1);
System.out.println("You rated this film: "+filmRatingOutOfFive+" out of 5");
}
答案 1 :(得分:2)
对,所以Decodable实际上非常聪明,因为你真的不需要编写任何代码来自己进行解码。您只需确保匹配JSON结构(并为任何嵌套对象创建也符合Decodable的结构)。换句话说,不要将变量作为字典,而是将它们作为自己的Decodable结构。
例如:
struct EventBrite: Decodable {
let pagination: Pagination
let events: [Event]
}
struct Pagination: Decodable {
let page_number: Int
let page_size: Int
let continuation: String
let has_more_items: Bool
}
struct Event: Decodable {
let name: EventName
let description: EventDescription
}
struct EventName: Decodable {
let name: String
let html: String
}
等...
其他重要的事情是,如果无法保证返回密钥或财产(例如,让我们说EventName
并不总是有一个html值从服务器返回,您可以轻松地将该值标记为可选。所以类似于:
struct EventName: Decodable {
let name: String
let html: String?
}
另一方面,您实际上搞砸了您的字典类型声明。您会注意到event
实际上是[String: [String: String]]
类型,因为键是一个字符串,值似乎总是字典。名字是[String: String]
。这不是你原来问题中的原因。
如果值与分页不同,您可能会执行[String: Any]
之类的操作,所以请小心。
HOWEVER 我认为我认为的方法比将属性设为字典更好。对于一个你不必担心声明它的字典类型(你做了一些小错误)。但更重要的是,当每个词典成为自己明确定义的结构时,您不必担心记住或查找键。点语法/自动完成会自动告诉你可以有什么! (当您的值为Any
或AnyObject
类型时,不会进行转换!)
同样明确地使用所有这些结构,因为我曾经对性能和测量结构效率进行基准测试,其效率比类别高出数百万倍。只是一个FYI。