Swift 5:使用 Codable / Struct 从我的变量创建 JSON

问题描述 投票:0回答:3

我想创建一个可编码结构来保存用户配置文件中的数据。 假设 iOS 用户填写了一个表单,其中包含他的姓名、地址、图片 (UIImage),并且该用户有一个唯一的 ID。 我的 JSON 会是这样的:

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

我尝试创建可编码的但我认为它不是最佳的,您能否给我一些优化它的提示或告诉我这样做是否错误?

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)
}

之后,我想使用 Haneke swift (https://github.com/Haneke/HanekeSwift) 或 Datacache (https://github.com/huynguyencong/DataCache) 来缓存它。如何缓存我的 Codable? (例如,我没有使用 Haneke 查看任何“为 json 设置缓存”)

最后,我想在使用 SwiftyJSON 获取后使用它:(https://github.com/SwiftyJSON/SwiftyJSON),我不知道我的 Codables 是否足够可读。

感谢您的想法/评论!

json swift codable swifty-json haneke
3个回答
2
投票

由于您可以完全控制您的结构并且不涉及集合,因此我建议将所有内容放入一个结构中,而不是将其分散在许多不同的结构中:

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

关于缓存。正如您可以将此结构标记为

Codable
一样,它可以轻松地存储在
Userdefaults
中作为
Data
Userdefaults
上的此扩展应该允许您以类型安全的方式访问
UserProfile

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")
        }
    }
}

使用示例:

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

编辑: 编辑示例:

由于这是一个结构体,每次发生变化时它都会被复制。 因此读取 var 中的值。修改并保存到defaultStore。

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

1
投票

您提供的示例不是有效的 JSON。它看起来像是字典和数组的某种混合体。

所以让我们做一些调整:

{
  "Unique_ID": "1234556778",
  "Data_of_User": {
    "First_Name": "John",
    "Last_Name": "Doe",
    "Address": {
      "Street": "21 jump street",
      "Country": "USA"
    }
  }
}

然后您可以创建如下所示的结构:

struct UserProfile: Codable {
    let uniqueID: String
    let userData: UserData
    
    enum CodingKeys: String, CodingKey {
        case uniqueID = "Unique_ID"
        case userData = "Data_of_User"
    }
}

struct UserData: Codable {
    let firstName: String
    let lastName: String
    let address: Address
    
    enum CodingKeys: String, CodingKey {
        case firstName = "First_Name"
        case lastName = "Last_Name"
        case address = "Address"
    }
}

struct Address: Codable {
    let street: String
    let country: String
    
    enum CodingKeys: String, CodingKey {
        case street = "Street"
        case country = "Country"
    }
}

0
投票

Codable 要求结构中的属性名称与 json 对应项匹配。 在您的

User_Profile_Data
结构中,您有
name
,而 json 包含
"Name"
,并且您有
last_name
,其中 json 包含
"Last Name"

解决此问题的一种方法是向结构添加一个

CodingKeys

 枚举,告诉它如何映射属性。
所以在你的 
User_Profile_Data
 结构中我会添加:

enum CodingKeys: String, CodingKey { case name = "Name" case last_name = "Last Name" case adress }


    

© www.soinside.com 2019 - 2024. All rights reserved.