skip to Main Content
import Foundation

struct RGBValue: Codable {
    let blue, green: Double
    let timestamp: String
    let red: Double
}

struct RGB: Codable {
    let fps: Double
    let heartRate: Int
    let rgbValues: [RGBValue]
    
    static let rgbData: [RGB] = Bundle.main.decode(file: "hrv_data.json")
    static let sampleData: RGB = rgbData[0]
}




extension Bundle{
    
    func decode<T: Decodable>(file: String) -> T {
        guard let url = self.url(forResource: file, withExtension: nil) else {
            fatalError("Could not find (file) in the project!")
        }
        guard let data = try? Data(contentsOf: url) else {
            fatalError("Could not load (file) in the project!")
        }
        
        let decoder = JSONDecoder()
        
        guard let loadedData = try? decoder.decode(T.self, from: data) else {
            fatalError("Could not decode (file) in the project! error : (Error.self)")

        }
        return loadedData
    }
}

This is the entire code snippet which shows no error, but while run time it crashes "Thread 1: Fatal error: Could not decode hrv_data.json in the project! error : Error"
How to solve the issue and know the reason behind this error?

json sample:

{
  "fps": 0.1548667699098587,
  "heartRate": 81,
  "rgbValues": [
    {
      "blue": 0,
      "green": 0,
      "timestamp": "22-04-2024 10:33:57",
      "red": 0
    }
  ]
}

2

Answers


  1. I really appreciate Paul Hudson’s huge effort for the Swift community, but this Bundle extension he suggests to decode a JSON file is a poor advice, I’m afraid.

    It’s highly recommended to catch always the comprehensive DecodingError, it tells you exactly what’s wrong and even where the error occurred.

    Replace

    let loadedData = try? decoder.decode(T.self, from: data) else {
            fatalError("Could not decode (file) in the project! error : (Error.self)")
    }
    return loadedData
    

    with

    do {
        return try decoder.decode(T.self, from: data) 
    } catch {
        fatalError("Could not decode (file) in the project! Error: (error)")
    }
    

    The error is clear. The root object is a dictionary (note the enclosing {}), it’s not an array

    static let sampleData: RGB = Bundle.main.decode(file: "hrv_data.json")
    
    Login or Signup to reply.
  2. Try this example code using decode with do/catch returning an optional,
    plus various improvements:

    struct RGBValue: Identifiable, Codable { //<-- here
        let id = UUID()
        
        let blue, green, red: Double
        let timestamp: String
        
        enum CodingKeys: String, CodingKey {
            case blue, green, red, timestamp
        }
    }
    
    struct RGB: Codable {
        let fps: Double
        let heartRate: Int
        let rgbValues: [RGBValue]
        
        static let rgbData: [RGB] = Bundle.main.decode(file: "hrv_data.json") ?? [] //<-- here
      //  static let sampleData: RGB = rgbData[0]  // <-- not here
    }
    
    extension Bundle{
        
        func decode<T: Decodable>(file: String) -> T? { //<-- here
            guard let url = self.url(forResource: file, withExtension: nil) else {
                fatalError("Could not find (file) in the project!")
            }
            do { //<-- here
                let data = try Data(contentsOf: url)
                return try JSONDecoder().decode(T.self, from: data)
            } catch {
                print("---> error: (error)") //<-- here, important
            }
            return nil //<-- here
        }
    }
    
    struct ContentView: View {
        var body: some View {
            Text("testing")
                .onAppear {
                    print("---> rgbData: (RGB.rgbData)")
                }
        }
    }
    

    File hrv_data.json content

     [
     {
         "fps" : 0.1548667699098587,
         "heartRate" : 81,
         "rgbValues" : [
             {
                 "blue" : 0,
                 "green" : 0,
                 "timestamp" : "22-04-2024 10:33:57",
                 "red" : 0
             }
         ]
     }
     ]
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search