Swift 存储无序数据文件中的值

Swift 存储无序数据文件中的值,swift,mapbox,geojson,Swift,Mapbox,Geojson,在分析/循环无序的数据文件时,如何将值存储到对象或变量中以供以后使用 实际文件是一个GeoJSON文件,其中包含高尔夫洞特征的地图坐标,其中定义了两种类型(多边形或点)的许多地理对象。以下是一个小样本: { "features": [ { "type": "Feature", "properties": { "holeno": 19, "feature": "teebox" }, "geometry":

在分析/循环无序的数据文件时,如何将值存储到对象或变量中以供以后使用

实际文件是一个GeoJSON文件,其中包含高尔夫洞特征的地图坐标,其中定义了两种类型(多边形或点)的许多地理对象。以下是一个小样本:

{
  "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"
}
我希望能够将这些存储到类、变量或对象中,以供以后使用/处理。但是无序的结构给我带来了问题,特别是在数据类型的选择和初始化方面

数组有自己的索引,从0开始,不能使用insert(at:)函数以随机数插入

字典只存储一个键值对。我有2个地图坐标每个洞,加上至少3个多边形,但可能更多

一个结构的初始化比较简单,但在创建每个结构时,我只知道1个属性的值。我可以为每个属性使用可选值,但建议用什么方法来完成实例对所有属性的初始化?如何检查特定孔的实例之前是否已创建

类与结构具有相同的问题,但在初始化方面更复杂


我刚刚接触和学习Swift,所以我是否遗漏或误解了上述数据类型?是否有一种方法可以实现我可能从未听说过的上述功能?

[Swift 4]基于您的Json结构,您必须使用Codable设计您的模型类/结构。根据您的示例,我发现4个模型结构足以将json映射到对象

首先创建根模型结构,该结构将保存另一个结构,如功能

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

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

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

[Swift 4]基于您的Json结构,您必须使用Codable设计您的模型类/结构。根据您的示例,我发现4个模型结构足以将json映射到对象

首先创建根模型结构,该结构将保存另一个结构,如功能

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

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

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

听起来像是
Codable
jsonecoder/Decoder
的工作@非常感谢。我已经开始搜索可编码协议。。。找到了一个不错的Youtube视频,由一个Couchbase的家伙发布,由“IBM数据”发布。。。听起来像是
Codable
jsonecoder/Decoder
的工作@非常感谢。我已经开始搜索可编码协议。。。找到了一个不错的Youtube视频,由一个Couchbase的家伙发布,由“IBM数据”发布。。。感谢您提供的示例代码,当尝试应用我正在阅读和学习的
Codable
协议,并能够将其与您的代码对照作为参考时,它将非常有用。我正试图建立自己(从内向外工作),并已达到一个挑战。。。任何
“多边形”
类型的特征都有一个三重嵌套的
[Double]
(我不知道为什么…),但
“点”
类型的特征只有一个Double数组。如何区分和/或编码?最好是在服务器端更改坐标的对称类型,否则必须从[Double]->[[Double]]转换。请检查geometry struct“init”中的更新代码。虽然我可以通过在地图上绘制来创建内容,但我正在从Mapbox下载生成的GeoJSON文件/内容,因此我无法控制格式。我不想编辑我将制作的每个文件,但有一个更好的方法对其进行初始解析。。。我首先将Geometry.coordinates设置为
[Double]
类型,发现了这个问题-下一次运行时,它抱怨看到一个项目数组。是否可以使用您的样式/代码对解析进行分支,1用于
另一个用于
多边形
?@Razib(如果您仍在关注此线程!),
Geometry
struct的
coordinate
属性是否属于
Any
类型,以便从我下载的GeoJSON文件中绕过2种不同的数组结构?因此,对于一个“点”,它只能是一个
[Double]
,但是对于一个“多边形”,它将是一个
[[[Double]]]]
?您不能使用任何。如何使用类似枚举GeoType的枚举可编码:可编码{case singleDouble([Double]),case tripleDouble([[[Double]])init(来自解码器:解码器){make condition code}}。在Geometry结构中,use coordinates=GeoType&init:coordinates=try GeoType.init(from:decoder)。我不知道其他方法。感谢示例代码,当尝试应用我正在阅读的内容和学习的
Codable
协议,并能够将其与您的代码对照作为参考时,它将非常有用。我正试图建立自己(从内向外工作),并已达到一个挑战。。。任何
“多边形”
类型的特征都有一个三重嵌套的
[Double]
(我不知道为什么…),但
“点”
类型的特征只有一个Double数组。如何区分和/或编码?最好是在服务器端更改坐标的对称类型,否则必须从[Double]->[[Double]]转换。请检查geometry struct“init”中的更新代码。虽然我可以通过在地图上绘制来创建内容,但我正在从Mapbox下载生成的GeoJSON文件/内容,因此