Cannot Parse JSON data

Can anyone help solve the error here? I continue to get the fatal error in the ModelData.swift file: "Couldn't parse quotes.json as Array". I have validated the JSON file on JSONLint as well.

Here are the project files: LINK

I am new to SwiftUI so any help is very appreciated.

Model Data:

import Foundation

import Combine



final class ModelData: ObservableObject {

    @Published var quotes: [Quote] = load("quotes.json")

}





func load<T: Decodable>(_ filename: String) -> T {

    let data: Data

    guard let file = Bundle.main.url(forResource: filename, withExtension: nil)

    else {

        fatalError("Couldn't find \(filename) in main bundle")

    }

    do {

        data = try Data(contentsOf: file)

    } catch {

        fatalError("Couldn't load \(filename) from main bundle:\n\(error)")

    }

    do {

        let decoder = JSONDecoder()

        return try decoder.decode(T.self, from: data)

    } catch {

        fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")

    }

}


Model:


import SwiftUI



struct Quote: Codable, Identifiable, Hashable {

    var id: Int

    var readDate: Date?

    var quote: String

    var author: String

    var isFavorited: Bool

    

    var displayAuthor: String {

        "- \(author)"

    }

    var formattedDate: String {

        readDate?.formatted(date: .numeric, time: .omitted) ?? "N/A"

    }

    var dayDate: String {

        readDate?.formatted(.dateTime.day()) ?? "N/A"

    }

}

JSON File:

[

    {

        "id": 1,

        "readDate": "11.12.2022",

        "quote": "If you judge a fish by its ability to climb a tree then it will go its whole live beliving it's stupid.",

        "author": "Albert Einstein",

        "isFavorited": false

    },

    {

        "id": 2,

        "readDate": "11.13.2022",

        "quote": "Do or do not. There is no try.",

        "author": "Master Yoda",

        "isFavorited": true

    },

    {

        "id": 3,

        "readDate": "11.14.2022",

        "quote": "Learn as if you will live forever, live like you will die tomorrow.",

        "author": "Mahatma Gandhi",

        "isFavorited": false

    },

    {

        "id": 4,

        "readDate": "11.15.2022",

        "quote": "When you change your thoughts, remember to also change your world.",

        "author": "Norman Vincent Peale",

        "isFavorited": false

    },

    {

        "id": 5,

        "readDate": "11.16.2022",

        "quote": "Success is not final; failure if not fatal: It is the courage to continue that counts.",

        "author": "Winston S. Churchill",

        "isFavorited": false

    },

    {

        "id": 6,

        "readDate": "11.17.2022",

        "quote": "Success is getting what you want, happiness is wanting what you get.",

        "author": "W. P. Kinsella",

        "isFavorited": false

    },

    {

        "id": 7,

        "readDate": "11.18.2022",

        "quote": "Successs usually comes to those who are too busy looking for it.",

        "author": "Henry David Thoreau",

        "isFavorited": false

    },

    {

        "id": 8,

        "readDate": "11.19.2022",

        "quote": "Don't let yesterday take up too much of today.",

        "author": "Will Rogers",

        "isFavorited": false

    },

    {

        "id": 9,

        "readDate": "11.20.2022",

        "quote": "You miss 100% of the shots you don't take.",

        "author": "Wayne Gretzky",

        "isFavorited": true

    }

]
Answered by robnotyou in 736883022

Your json is formatting dates like "11.12.2022", which is MM.dd.yyyy
You need to provide this format to your JSONDecoder.

I generally use a DateFormatter extension for this:

extension DateFormatter {
    
    static let jsonDateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.locale = Locale.autoupdatingCurrent
        formatter.dateFormat = "MM.dd.yyyy"
        return formatter
    }()
}

Then you simply pass this to your JSONDecoder, like this:

do {
	let decoder = JSONDecoder()
	decoder.dateDecodingStrategy = .formatted(DateFormatter.jsonDateFormatter)
	return try decoder.decode(T.self, from: data)
}

In your Quote class you have var readDate: Date?, but you can't store a Date object in JSON, you have to use a String. Your quotes.json file does correctly store it as a String, so you need to rewrite your Quote class to handle a String rather than a Date.

Accepted Answer

Your json is formatting dates like "11.12.2022", which is MM.dd.yyyy
You need to provide this format to your JSONDecoder.

I generally use a DateFormatter extension for this:

extension DateFormatter {
    
    static let jsonDateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.locale = Locale.autoupdatingCurrent
        formatter.dateFormat = "MM.dd.yyyy"
        return formatter
    }()
}

Then you simply pass this to your JSONDecoder, like this:

do {
	let decoder = JSONDecoder()
	decoder.dateDecodingStrategy = .formatted(DateFormatter.jsonDateFormatter)
	return try decoder.decode(T.self, from: data)
}
Cannot Parse JSON data
 
 
Q