[英]How to architecture a json object model in swift with Codable protocol
I'm coding a REST Web app client and I use JSON which looks like this:我正在编写 REST Web 应用程序客户端,并使用如下所示的 JSON:
JSON1 JSON1
{
"device" : "iPhone"
"manufacturer" : "Apple"
"id" : 42
"owner" : "Steve"
}
But the API could give me this kind of JSON also但是 API 也可以给我这种 JSON
JSON2 JSON2
{
"device" : "iPhone"
"manufacturer" : "Apple"
"id" : 42
"latitude" : 3.1415926535
"longitude" : 2.7182818284
}
So now in my app I create a struct who conforms to the Codable protocol所以现在在我的应用程序中,我创建了一个符合 Codable 协议的结构
struct MyStruct : Codable {
var name: String
var manufacturer: String
var owner: String?
// I prefer to use a property of type Location rather than 2 variables
var location: Location? {
guard let latitude = latitude, let longitude = longitude else {
return nil
}
return Location(latitude: latitude, longitude: longitude)
}
// Used to conform to the Codable protocol
private var latitude: Double?
private var longitude: Double?
}
struct Location {
var latitude: Double = 0.0
var longitude: Double = 0.0
}
This architecture works but it seems to me not the best one or elegant.这种架构有效,但在我看来它不是最好的或优雅的。 Would you know if a better approach exists?
你知道是否存在更好的方法吗? Should I use 2 differents json model instead like:
我是否应该使用 2 个不同的 json 模型,例如:
struct MyStruct1 : Codable {
var name: String
var manufacturer: String
var owner: String
}
struct MyStruct2 : Codable {
var name: String
var manufacturer: String
private var latitude: Double
private var longitude: Double
}
I'm new to REST API client and this kind of JSON doesn't seems to use a good architecture.我是 REST API 客户端的新手,这种 JSON 似乎没有使用好的架构。
Make the owner
, latitude
& longitude
properties optional.将
owner
、 latitude
和longitude
属性设为可选。 And use decodeIfPresent
for decoding properties only when they exists.并且仅当属性存在时才使用
decodeIfPresent
进行解码。
You can create a struct
as-您可以创建一个
struct
-
struct UserData: Codable {//Confroms to Codable protocol
var id: Int
var device: String
var manufacturer: String
var owner: String? = nil//Making property optional
var latitude: Double? = nil//Making property optional
var longitude: Double? = nil//Making property optional
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
id = try values.decode(Int.self, forKey: .id)
device = try values.decode(String.self, forKey: .device)
manufacturer = try values.decode(String.self, forKey: .manufacturer)
owner = try values.decodeIfPresent(String.self, forKey: .owner)
latitude = try values.decodeIfPresent(Double.self, forKey: .latitude)
longitude = try values.decodeIfPresent(Double.self, forKey: .longitude)
}
}
Example Json:示例 Json:
let jsonExample = """
{
"device" : "iPhone",
"manufacturer" : "Apple",
"id" : 42,
"owner" : "Steve"
}
""".data(using: .utf8)!
let jsonExample2 = """
{
"device" : "iPhone",
"manufacturer" : "Apple",
"id" : 42,
"latitude" : 3.1415926535,
"longitude" : 2.7182818284
}
""".data(using: .utf8)!.
Usage:用法:
//Decode struct using JSONDecoder
let jsonDecoder = JSONDecoder()
do {
let modelResult = try jsonDecoder.decode(UserData.self,from: jsonExample2)
print("owner is \(String(describing: modelResult.owner)) - latitude is \(String(describing: modelResult.latitude)) - longitude is \(String(describing: (modelResult.longitude)))")
} catch {
print(error)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.