UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SOLVED: Decoding JSON

Forums > Swift

Hi community,

Sorry for the basic question, but since yesterday I am not able to decode this JSON data. I have implemented the Bundle-Decodable from the Moonshot project.

Getting this error: Fatal error: Failed to decode scales.json from bundle.

[
    {
        "id": "pA",
        "scales": [
            {
                "activity" : "Legato Pentascales",
                "key": "C, G, D, Am",
                "played": "Hands Separated",
                "playedDesc": "Tonic to dominat, ascending and descending, ending with solid root-position triad",
                "tempoValue": "100",
                "noteValue:": "quarter"
            },
            {
                "activity" : "Staccato Pentascales",
                "key": "C, G, D, Am",
                "played": "Hands Separated",
                "playedDesc": "Tonic to dominat, ascending and descending, ending with solid root-position triad",
                "tempoValue": "100",
                "noteValue:": "quarter-staccato"
            }
        ]
    },
    {
        "id": "pB",
        "scales": [
            {
                "activity" : "Legato Pentascales",
                "key": "D, A, F, Em, Dm",
                "played": "Hands Separated",
                "playedDesc": "Tonic to dominat, ascending and descending, ending with solid root-position triad",
                "tempoValue": "60",
                "noteValue:": "2-eighth"
            },
            {
                "activity" : "Staccato Pentascales",
                "key": "D, A, F, Em, Dm",
                "played": "Hands Separated",
                "playedDesc": "Tonic to dominat, ascending and descending, ending with solid root-position triad",
                "tempoValue": "60",
                "noteValue:": "2-eighth-staccato"
            },
            {
                "activity" : "One-octave Scales",
                "key": "C, G, Am (natural)",
                "played": "Hands Separated",
                "playedDesc": "One-octave",
                "tempoValue": "60",
                "noteValue:": "2-eighth"
            },
            {
                "activity" : "Contrary Motion Scale",
                "key": "C",
                "played": "Hands Together",
                "playedDesc": "One-octave",
                "tempoValue": "60",
                "noteValue:": "2-eighth"
            }
        ]
    }

]

This is my struct:

import Foundation

struct TechRequirements: Codable, Identifiable  {

    let id: String
    let scales: [Scale]

}

struct Scale: Codable {

    let activity: String
    let key: String
    let played: String
    let playedDesc: String
    let tempoValue: String
    let noteValue: String

}

Bundle-Decodable:

import Foundation

extension Bundle {
    func decode<T: Codable>(_ file: String) -> T {
        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()

        guard let loaded = try? decoder.decode(T.self, from: data) else {
            fatalError("Failed to decode \(file) from bundle.")
        }

        return loaded
    }
}

My DataManager:

import Foundation

class DataManager: ObservableObject {

    @Published var scales: [TechRequirements] = Bundle.main.decode("scales.json")

}

Thanks for the support. Renato.

2      

Instead of this:

guard let loaded = try? decoder.decode(T.self, from: data) else {
    fatalError("Failed to decode \(file) from bundle.")
}

return loaded

give yourself a chance to see what the error is:

do {
    let loaded = try decoder.decode(T.self, from: data)
    return loaded
} catch {
    fatalError("\(error)")
}

and see what gets printed to the console.

If you search around here on the forums, you can even find other ways of doing a similar thing that give you a prettier, more user-friendly error description, but I find the above works well enough.

For this particular case, I would suggest taking a closer look at your JSON keys compared to the corresponding property names in your structs.

2      

Thanks for the code and help. I found the error on the noteValue key. There was a ":" inside.

Here is the error message.:

2023-02-09 22:02:02.834915-0600 Syllabus[6840:6509202] Syllabus/Bundle-Decodable.swift:33: Fatal error: keyNotFound(CodingKeys(stringValue: "noteValue", intValue: nil), Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "scales", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "No value associated with key CodingKeys(stringValue: \"noteValue\", intValue: nil) (\"noteValue\").", underlyingError: nil))

Thanks again, Renato.

2      

BUILD THE ULTIMATE PORTFOLIO APP Most Swift tutorials help you solve one specific problem, but in my Ultimate Portfolio App series I show you how to get all the best practices into a single app: architecture, testing, performance, accessibility, localization, project organization, and so much more, all while building a SwiftUI app that works on iOS, macOS and watchOS.

Get it on Hacking with Swift+

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.