存储无序数据文件中的值
Store values from an unordered data file
当您解析/循环遍历无序的数据文件时,如何将值存储到对象或变量中供以后使用?
实际文件是一个 GeoJSON 文件,其中包含高尔夫球洞特征的地图坐标,其中定义了许多 2 种类型(多边形或点)的地理对象。以下是一个小样本:
{
"features": [
{
"type": "Feature",
"properties": {
"holeno": 19,
"feature": "teebox"
},
"geometry": {
"coordinates": [
[
[
-1.478163,
53.869862
],
[
-1.478122,
53.869801
],
[
-1.477888,
53.869859
],
[
-1.477927,
53.869922
],
[
-1.478163,
53.869862
]
]
],
"type": "Polygon"
},
"id": "0351f53178c564588a506709c7039509"
},
{
"type": "Feature",
"properties": {
"holeno": 15,
"feature": "pastGreen"
},
"geometry": {
"coordinates": [
-1.472843,
53.871483
],
"type": "Point"
},
"id": "03850283164d2a7a63d1793baebff719"
},
{
"type": "Feature",
"properties": {
"holeno": 8,
"feature": "teebox"
},
"geometry": {
"coordinates": [
[
[
-1.479439,
53.875594
],
[
-1.47972,
53.875493
],
[
-1.479667,
53.875434
],
[
-1.479363,
53.87554
],
[
-1.479439,
53.875594
]
]
],
"type": "Polygon"
},
"id": "05a1644f6c7d11db4f802fb14b98b8b3"
}
],
"type": "FeatureCollection"
}
我希望能够将这些存储到 classes、变量或对象中以供以后使用/处理。但是无序结构给我带来了问题,特别是关于数据类型和初始化的选择。
数组有自己的索引,从 0 开始,您不能使用 insert(at:) 函数插入随机数。
字典只存储一个键值对。我每个洞有 2 个地图坐标,加上至少 3 个多边形,但可能更多。
结构的初始化更简单,但在创建每个结构时我只会知道 1 属性 的值。我可以为每个 属性 使用可选值,但是完成实例所有属性初始化的推荐方法是什么?我如何检查之前是否已经创建了特定孔的实例?
A class 与结构有相同的问题,但在初始化方面更复杂。
我是新手,正在学习 Swift,所以我是否遗漏或误解了上述数据类型的某些内容?有没有一种方法可以实现上述我可能没有听说过的方法?
[Swift 4] 根据您的 Json 结构,您必须使用 设计模型 classes/struct可编码。根据您的示例,我发现 4 个模型结构足以将您的 json 映射到一个对象。
首先创建 RootModel 结构,它将包含另一个结构,比如 Feature:
struct RootModel : Codable {
let features : [Features]?
let type : String?
enum CodingKeys: String, CodingKey {
case features = "features"
case type = "type"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
features = try values.decodeIfPresent([Features].self, forKey: .features)
type = try values.decodeIfPresent(String.self, forKey: .type)
}
}
现在您需要 Feature 模型结构,它将包含 Properties & Geometry:
struct Features : Codable {
let type : String?
let properties : Properties?
let geometry : Geometry?
let id : String?
enum CodingKeys: String, CodingKey {
case type = "type"
case properties
case geometry
case id = "id"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
type = try values.decodeIfPresent(String.self, forKey: .type)
properties = try Properties(from: decoder)
geometry = try Geometry(from: decoder)
id = try values.decodeIfPresent(String.self, forKey: .id)
}
}
几何与属性结构:
struct Properties : Codable {
let holeno : Int?
let feature : String?
----- similar CodingKeys & init----
}
struct Geometry : Codable {
let coordinates : [[[Double]]]?
let type : String?
----- similar CodingKeys & init----
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: Features.CodingKeys.self)
let geoValues = try values.nestedContainer(keyedBy: CodingKeys.self, forKey: .geometry)
type = try geoValues.decodeIfPresent(String.self, forKey: .type)
if type == "Point" {
let pointVal = try geoValues.decodeIfPresent([Double].self, forKey: .coordinates)
let nestedVal = [[pointVal]]
coordinates = nestedVal as? [[[Double]]]
} else {
coordinates = try geoValues.decodeIfPresent([[[Double]]].self, forKey: .coordinates)
}
}
}
最后,只需使用 RootModel 结构,如下所示:
let data: Data? = your_json_string.data(using: .utf8)
let jsonDecoder = JSONDecoder()
let responseModel = try! jsonDecoder.decode(RootModel.self, from: data!)
当您解析/循环遍历无序的数据文件时,如何将值存储到对象或变量中供以后使用?
实际文件是一个 GeoJSON 文件,其中包含高尔夫球洞特征的地图坐标,其中定义了许多 2 种类型(多边形或点)的地理对象。以下是一个小样本:
{
"features": [
{
"type": "Feature",
"properties": {
"holeno": 19,
"feature": "teebox"
},
"geometry": {
"coordinates": [
[
[
-1.478163,
53.869862
],
[
-1.478122,
53.869801
],
[
-1.477888,
53.869859
],
[
-1.477927,
53.869922
],
[
-1.478163,
53.869862
]
]
],
"type": "Polygon"
},
"id": "0351f53178c564588a506709c7039509"
},
{
"type": "Feature",
"properties": {
"holeno": 15,
"feature": "pastGreen"
},
"geometry": {
"coordinates": [
-1.472843,
53.871483
],
"type": "Point"
},
"id": "03850283164d2a7a63d1793baebff719"
},
{
"type": "Feature",
"properties": {
"holeno": 8,
"feature": "teebox"
},
"geometry": {
"coordinates": [
[
[
-1.479439,
53.875594
],
[
-1.47972,
53.875493
],
[
-1.479667,
53.875434
],
[
-1.479363,
53.87554
],
[
-1.479439,
53.875594
]
]
],
"type": "Polygon"
},
"id": "05a1644f6c7d11db4f802fb14b98b8b3"
}
],
"type": "FeatureCollection"
}
我希望能够将这些存储到 classes、变量或对象中以供以后使用/处理。但是无序结构给我带来了问题,特别是关于数据类型和初始化的选择。
数组有自己的索引,从 0 开始,您不能使用 insert(at:) 函数插入随机数。
字典只存储一个键值对。我每个洞有 2 个地图坐标,加上至少 3 个多边形,但可能更多。
结构的初始化更简单,但在创建每个结构时我只会知道 1 属性 的值。我可以为每个 属性 使用可选值,但是完成实例所有属性初始化的推荐方法是什么?我如何检查之前是否已经创建了特定孔的实例?
A class 与结构有相同的问题,但在初始化方面更复杂。
我是新手,正在学习 Swift,所以我是否遗漏或误解了上述数据类型的某些内容?有没有一种方法可以实现上述我可能没有听说过的方法?
[Swift 4] 根据您的 Json 结构,您必须使用 设计模型 classes/struct可编码。根据您的示例,我发现 4 个模型结构足以将您的 json 映射到一个对象。
首先创建 RootModel 结构,它将包含另一个结构,比如 Feature:
struct RootModel : Codable {
let features : [Features]?
let type : String?
enum CodingKeys: String, CodingKey {
case features = "features"
case type = "type"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
features = try values.decodeIfPresent([Features].self, forKey: .features)
type = try values.decodeIfPresent(String.self, forKey: .type)
}
}
现在您需要 Feature 模型结构,它将包含 Properties & Geometry:
struct Features : Codable {
let type : String?
let properties : Properties?
let geometry : Geometry?
let id : String?
enum CodingKeys: String, CodingKey {
case type = "type"
case properties
case geometry
case id = "id"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
type = try values.decodeIfPresent(String.self, forKey: .type)
properties = try Properties(from: decoder)
geometry = try Geometry(from: decoder)
id = try values.decodeIfPresent(String.self, forKey: .id)
}
}
几何与属性结构:
struct Properties : Codable {
let holeno : Int?
let feature : String?
----- similar CodingKeys & init----
}
struct Geometry : Codable {
let coordinates : [[[Double]]]?
let type : String?
----- similar CodingKeys & init----
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: Features.CodingKeys.self)
let geoValues = try values.nestedContainer(keyedBy: CodingKeys.self, forKey: .geometry)
type = try geoValues.decodeIfPresent(String.self, forKey: .type)
if type == "Point" {
let pointVal = try geoValues.decodeIfPresent([Double].self, forKey: .coordinates)
let nestedVal = [[pointVal]]
coordinates = nestedVal as? [[[Double]]]
} else {
coordinates = try geoValues.decodeIfPresent([[[Double]]].self, forKey: .coordinates)
}
}
}
最后,只需使用 RootModel 结构,如下所示:
let data: Data? = your_json_string.data(using: .utf8)
let jsonDecoder = JSONDecoder()
let responseModel = try! jsonDecoder.decode(RootModel.self, from: data!)