I have this local JSON File, which contains title, start and end. I want to create dates from the start and end keys, but a String for the title, so I can create Event objects. Right now I have decoded everything into Strings. So I'm trying to create a custom init, but an error keeps showing up "Return from initializer without initializing all stored properties". Not sure what am I doing wrong
Here's my Event model and my JSONFile
struct Event: Decodable & Equatable {
let title : String
let start : Date
let end : Date
//Custom decoding init
init(from decoder : Decoder) throws {
let container = try decoder.singleValueContainer()
let stringType = try container.decode(String.self)
switch stringType {
case "title":
self.title = try container.decode(String.self)
case "start":
self.start = try container.decode(Date.self)
case "end":
self.end = try container.decode(Date.self)
default:
throw DecodingError.dataCorruptedError(in: container, debugDescription: "Not valid date \(stringType)")
}
}
}
JSON
[{"title": "Evening Picnic", "start": "November 10, 2018 6:00 PM", "end": "November 10, 2018 7:00 PM"}, {"title": "Nap Break", "start": "November 8, 2018 12:30 PM", "end": "November 8, 2018 1:30 PM"}, {"title": "Football Game", "start": "November 3, 2018 6:00 PM", "end": "November 3, 2018 10:00 PM"}, {"title": "Evening Cookout with Friends", "start": "November 6, 2018 5:00 PM", "end": "November 6, 2018 10:00 PM"}, {"title": "Roller Derby", "start": "November 7, 2018 12:00 PM", "end": "November 7, 2018 2:30 PM"}, {"title": "Basketball Game", "start": "November 8, 2018 7:30 PM", "end": "November 8, 2018 10:30 PM"}, {"title": "Local Pub with Friends", "start": "November 1, 2018 7:30 PM", "end": "November 1, 2018 11:00 PM"}, {"title": "Dentist Appointment", "start": "November 10, 2018 1:45 PM", "end": "November 10, 2018 2:30 PM"}, {"title": "Free Donuts", "start": "November 9, 2018 3:00 PM", "end": "November 9, 2018 4:00 PM"}, {"title": "TV Show Marathon", "start": "November 9, 2018 4:30 PM", "end": "November 9, 2018 9:00 PM"}, {"title": "Lunch with Friends", "start": "November 8, 2018 11:30 AM", "end": "November 8, 2018 1:00 PM"}, {"title": "SF Coffee Festival","start": "November 6, 2018 6:00 PM","end": "November 6, 2018 9:00 PM"}, {"title": "Beer with Friends", "start": "November 9, 2018 8:00 PM", "end": "November 9, 2018 9:30 PM"}, {"title": "Yoga", "start": "November 1, 2018 6:00 PM", "end": "November 1, 2018 7:30 PM"}, {"title": "Rock Concert", "start": "November 7, 2018 6:30 PM", "end": "November 7, 2018 11:00 PM"}, {"title": "Lunch Meeting", "start": "November 9, 2018 12:30 PM", "end": "November 9, 2018 2:30 PM"}, {"title": "Bicycling with Friends", "start": "November 1, 2018 6:00 AM", "end": "November 1, 2018 9:30 AM"}, {"title": "Birthday Party", "start": "November 10, 2018 12:30 PM", "end": "November 10, 2018 8:30 PM"}, {"title": "Football Tailgate with John", "start": "November 3, 2018 6:00 PM", "end": "November 3, 2018 10:00 PM"}]
CodePudding user response:
If you declare constant variable and not initialized, the following error occurs.
Return from initializer without initializing all stored properties.
try this ! :)
struct Event: Decodable & Equatable {
var title : String? = ""
var start : Date? = nil
var end : Date? = nil
//Custom decoding init
init(from decoder : Decoder) throws {
let container = try decoder.singleValueContainer()
let stringType = try container.decode(String.self)
switch stringType {
case "title":
self.title = try container.decode(String.self)
case "start":
self.start = try container.decode(Date.self)
case "end":
self.end = try container.decode(Date.self)
default:
throw DecodingError.dataCorruptedError(in: container, debugDescription: "Not valid date \(stringType)")
}
}
}
CodePudding user response:
-> firstly you need to accept proper JSON Data
-> then you need to create a codable class or a struct
struct Main: Codable {
var data: [Datum]?
}
// MARK: - Datum
struct MYStruct: Codable {
var title, start, end: String?
}
-> if the key "start": "November 3, 2018 6:00 PM" here "start" deffers you can use codingKey like this
struct MYStruct: Codable {
var title, start, end: String?
enum CodingKeys: String, CodingKey {
case title = "title" // key name as string
case startDate = "start"
case endDate = "end"
}
-> then Create a JSON decoder to decode jsonData
let decoder = JSONDecoder()
let loadedData = try? decoder.decode(Main, from: JSONData) // 1st parameter object name 2nd parameter JsonData
-> keep in mind you json is always proper strat and ends with {}
-> always should be in key pair value