skip to Main Content

I have a problem with a JSON file the app crashes when it starts decoding and therefore the data is not loaded. I downloaded it from Facebook to test and I got the Facebook JSON file with all the friends in my account and the format is this:

{
  "friends_v2": [
    {
      "name": "Test Test",
      "timestamp": 1678361485
    },
    {
      "name": "Test2 ",
      "timestamp": 1678318229
    },
    {
      "name": "Test 3",
      "timestamp": 1675869376
    }
    ]
  }

As you can see the file doesn’t start with name and timestamp but before them there is "friends_v2". I noticed that if I delete that "friend_v2" everything works otherwise it doesn’t.

[
    {
      "name": "Test Test",
      "timestamp": 1678361485
    },
    {
      "name": "Test2 ",
      "timestamp": 1678318229
    },
    {
      "name": "Test 3",
      "timestamp": 1675869376
    }
  ]

In case I get uneditable JSON like this (so I can’t delete "friend_v2") how can I make everything work? Thank you very much for your time


This is my JSONManager.swift

struct Friends: Codable {
    var name: String
    var timestamp: Int
    var contact_info: String?

    
    static let allFriends: [Friends] = Bundle.main.decode(file: "friends.json")
    static let allFriendsSample: Friends = allFriends[0]
}

extension Bundle {
    func decode<T: Decodable>(file: String) -> T {
        guard let url = self.url(forResource: file, withExtension: nil) else {
            fatalError("Non è stato possibile trovare il file (file) nel progetto")
        }
        
        guard let data = try? Data(contentsOf: url) else {
            fatalError("Non è stato possibile caricare il file (file) nel progetto")
        }
                
        let decoder = JSONDecoder()
        
        guard let loadData = try? decoder.decode(T.self, from: data) else {
            
            fatalError("Non è stato possibile decodificare il file (file) nel progetto")
        }
        
        return loadData
    }
}

And I use in ContentView

struct ContentView: View {
    
    private var friends: [Friends] = Friends.allFriends
    
    var body: some View {
        VStack {
            List {
                ForEach(friends, id: .name) { friend in
                    Text(friend.name)
                }
            }
        }
        .padding()
    }
}

3

Answers


  1. try this approach, using the following models.

    struct Friends: Codable {
        var name: String
        var timestamp: Int
        var contact_info: String?
     
        static let rootObj: RootObject = Bundle.main.decode(file: "friends.json")
        static let allFriends: [Friends] = rootObj.friendsV2
    
        static let allFriendsSample: Friends = allFriends[0]
    }
    
    struct RootObject: Codable {
        let friendsV2: [Friends]
    
        enum CodingKeys: String, CodingKey {
            case friendsV2 = "friends_v2"
        }
    }
    
    Login or Signup to reply.
  2. Since you are using fatalError, it means you are pretty sure about the errors.

    So instead: use try! instead of guard ... try? ... return { fatalError(...) }

    Then the compiler will tell you what is wrong with your code or the json


    ⚠️ Note that there is always a reason when a function is throwing and you should consider error handling instead of just silencing the compiler by using fatal.

    Login or Signup to reply.
  3. Here’s an updated version of your Friends struct that includes a friends_v2 property that maps to the array in the JSON data:

    struct Friends: Codable {
        let friends_v2: [Friend]
        
        struct Friend: Codable {
            let name: String?
            let timestamp: Int?
            let contact_info: String?
        }
        
        static let allFriends: [Friend] = {
            guard let url = Bundle.main.url(forResource: "friends", withExtension: "json"),
                  let data = try? Data(contentsOf: url),
                  let friends = try? JSONDecoder().decode(Friends.self, from: data)
            else {
                fatalError("Unable to load friends from JSON file")
            }
            return friends.friends_v2
        }()
        
        static let allFriendsSample: Friend = allFriends[0]
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search