Home > other >  Json not loading in SwiftUI
Json not loading in SwiftUI

Time:10-04

am trying to load this json into my swiftui app

 {
            "id": "EF1CC5BB-4785-4M8E-AB98-5FA4E00B6A66",
            "name" : "opening the box",
            "group" : [
            
            {
                "name" : "Open  box",
                "windows" : "Double-click",
                "mac" : "right-click"
                
            },
            {
                "name" : "Duplicate",
                "windows" : "right click and choose from options",
                "mac" : "option   drag"
                
            }
            
            
            
            
            ]
        },

and there are many more elements like this

and here are the structs that I made

struct topic: Codable, Identifiable {
    
    var id: UUID
    var name: String
    var group: [shortcuts]
    
    
}

struct shortcuts: Codable, Equatable, Identifiable{
    
    var id = UUID()
    var name: String
    var windows: String
    var mac: String

}

and here is the code for decoding it

import UIKit

extension Bundle {
    
    func decode<T: Decodable>(_ type: T.Type, from file: String) -> T {
        
        guard let url = self.url(forResource: file, withExtension: nil) else {
            
            fatalError("failed")
      
        }
        
        guard let data = try? Data(contentsOf: url) else {
            
            
            fatalError("failed to do it")
            
        }
        
        let decoder = JSONDecoder()
        
        guard let loaded = try? decoder.decode(T.self, from: data) else {
            fatalError("failed")
        }
        return loaded
        
    }
    
    
    
    
}

now when I create a constant like this inside my view

 let Topic = Bundle.main.decode([topic].self, from: "main.json")

and then I try to load the items like this

 NavigationView{
                List{
                    ForEach(Topic) { section in
                        Section(header: Text(section.name)) {
                            ForEach(section.group) { item in
                                shortcutRow(item: item)
                            }
                        }
                        
                        
     
                }
                
            }.navigationBarTitle("Menu")
             .listStyle(SidebarListStyle())
                
            
        }

it doesn't work it shows fatal error that is present in the second last line of code of my bundle extension that I created for decoding this json

please help

CodePudding user response:

"...and there are many more elements like this", that means the json you show is probably not the json you have. Most likely it is an array of what you show. Thus, in Bundle decode, you should decode and return [T] not T. Note you should use the normal convention of using uppercased name for types, such as Topic, and lowercased name for instances, topic. Given that, try this:

extension Bundle {
    
    // todo deal with errors
    func decode<T: Decodable>(from file: String) -> [T] {  // <-- here
        if let url = Bundle.main.url(forResource: file, withExtension: "json") {
            do {
                let data = try Data(contentsOf: url)
                let loaded = try JSONDecoder().decode([T].self, from: data)  // <-- here
                return loaded
            } catch {
                // todo deal with errors
                print("---> error: \(error)")
            }
        } else {
            // todo deal with errors
            print("---> error url: ")
        }
        return []
    }
    
}

struct Topic: Codable, Identifiable {
    var id, name: String
    var group: [Shortcuts]
}

struct Shortcuts: Codable, Identifiable {
    let id = UUID()  // <-- here use let
    var name, windows, mac: String
}

struct ContentView: View {
    let topics: [Topic] = Bundle.main.decode(from: "main") // <-- here
    
    var body: some View {
       Text("testing topics: \(topics.count)")
        .onAppear {
            print("---> topics: \(topics)")
        }
    }
}

EDIT:

This is the json data I used to test my answer:

[
{
           "id": "EF1CC5BB-4785-4M8E-AB98-5FA4E00B6A66",
           "name" : "opening the box",
           "group" : [
           {
               "name" : "Open  box",
               "windows" : "Double-click",
               "mac" : "right-click"
           },
           {
               "name" : "Duplicate",
               "windows" : "right click and choose from options",
               "mac" : "option   drag"
           }
           ]
       }
]
  • Related