jsonswiftcodableswifty-jsonhaneke

Swift 5 : Create JSON with Codable / Struct from my variables


I would like to create a Codable structure to save data from a user profile. Let's say the iOS user filled a form with his name, last name, address, put his picture (UIImage) and that user have a unique ID. My JSON would be like:

{"Unique_ID": "1234556778", 
    {"Name": "John",
     "Last Name": "Doe",
     "adress":
        {"street": "21 jump street",
         "country": "USA"}
     } 
}

I tried to create the Codable but I think it isn't optimal, could you kindly give me some hint to optimize it or tell me if I'm wrong doing it like this ?

struct User_Profile: Codable {
    let Unique_ID: String
    let Data_Of_User: User_Profile_Data
}

struct User_Profile_Data: Codable {
    let name: String
    let last_name: String
    let adress : User_Adress_Data
}

struct User_Adress_Data: Codable {
    let street: String
    let country: String
}

override func viewDidLoad() {
    super.viewDidLoad()
            
    let usernametest = "John"
         
    let b = User_Adress_Data(street: "21 jump street", country: "USA")
    let c = User_Profile_Data(name: usernametest, last_name: "Doe", adress: b)
    let d = User_Profile(Unique_ID: "123456", Data_Of_User: c)
}

After that, I would like to cache it, with Haneke swift (https://github.com/Haneke/HanekeSwift), or Datacache (https://github.com/huynguyencong/DataCache). How can I cache my Codables? (for eg, I didn't view any 'set cache for json' with Haneke)

And finally, I would like to use it after fetched with SwiftyJSON: (https://github.com/SwiftyJSON/SwiftyJSON), and I don't know if my Codables are enought readable for it.

Thanks for your idea/comment !


Solution

  • As you have full controll over your structure and there is no collection involved i would recommend to put everything in one struct instead of scattering it over many different:

    struct UserProfile: Codable{
        var id: String
        var name: String
        var lastname: String
        var street: String
        var country: String
    }
    

    Regarding caching. As you can mark this struct Codable it can be easily stored in Userdefaults as Data. This extension on Userdefaults should allow you to access UserProfile in a typesafe manner.

    extension UserDefaults{
        var userProfile: UserProfile?{
            get{
                guard let data = data(forKey: "userProfile") else{
                    return nil
                }
                
                return try? JSONDecoder().decode(UserProfile.self, from: data)
            }
            set{
                set(try? JSONEncoder().encode(newValue), forKey: "userProfile")
            }
        }
    }
    

    Usage example:

    //Write
    UserDefaults.standard.userProfile = UserProfile(id: UUID().uuidString, name: "First", lastname: "Last", street: "nowhere", country: "atlantis")
    //Read
    let profile = UserDefaults.standard.userProfile
    

    Edit: Editing example:

    As this is a struct it gets copied every time something changes. So read the value in a var. Modify it and save it to the defaultStore.

    var profile = UserDefaults.standard.userProfile
    profile?.country = "newCountry"
    UserDefaults.standard.userProfile = profile