everyone. I am making an app for iOS. I use an API that allows to fetch city's sights as JSON.
Here is an example of the data:
{
"type":"FeatureCollection",
"features":[
{
"type":"Feature",
"id":"7281004",
"geometry":{
"type":"Point",
"coordinates":[]
},
"properties":{
"xid":"N5661720423",
"name":"М. В. Захарову",
"dist":70.53949268,
"rate":1,
"osm":"node/5661720423",
"kinds":"historic,monuments_and_memorials,interesting_places,monuments"
}
},
... 499 objects more
My solution for parsing in SWIFT is
import Foundation
struct SightResponse: Decodable, Hashable {
let allInfo = [String]()
enum CodingKeys: String, CodingKey{
case features
case type
enum FeatureKey: String, CodingKey{
case type
case id
}
}
}
extension SightResponse{
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
let type = try values.decode(String.self, forKey: .type)
let ContainsFeatures = values.contains(.features)
let features = try values.decode([String: String].self, forKey: .features)
//skips the features line
}
}
Also, at this line I tried different variations of data type such as
let features = try values.decode(String.self, forKey: .features)
or
let features = try values.decode([String].self, forKey: .features)
I am really confused.
I tried to change the parsing data type, but there is nothing new. I am trying to understand what I am doing wrong with my JSON data, and how I can understand what data type should be used in the future?
Codable
data types to parse the JSON objectsstruct FeatureCollection: Codable {
let type: String
let features: [Feature]
}
struct Feature: Codable {
let type: String
let id: String
let geometry: Geometry
let properties: Properties
}
struct Geometry: Codable {
let type: String
let coordinates: [Double]
}
struct Properties: Codable {
let xid: String
let name: String
let dist: Double
let rate: Int
let osm: String
let kinds: String
}
// Some dummy data with 2 features in the array
let jsonString = """
{
"type":"FeatureCollection",
"features":[
{
"type":"Feature",
"id":"1",
"geometry":{
"type":"Point",
"coordinates":[]
},
"properties":{
"xid":"N5661720423",
"name":"М. В. Захарову",
"dist":70.53949268,
"rate":1,
"osm":"node/5661720423",
"kinds":"historic,monuments_and_memorials,interesting_places,monuments"
}
},
{
"type":"Feature",
"id":"2",
"geometry":{
"type":"Point",
"coordinates":[]
},
"properties":{
"xid":"N5661720423",
"name":"М. В. Захарову",
"dist":70.53949268,
"rate":1,
"osm":"node/5661720423",
"kinds":"historic,monuments_and_memorials,interesting_places,monuments"
}
}
]
}
"""
// Decoding
let jsonData = jsonString.data(using: .utf8)!
let decoder = JSONDecoder()
let featureCollection = try! decoder.decode(FeatureCollection.self, from: jsonData)
to use a init(from decoder: Decoder)
constructor, look at this:
struct FeatureCollection: Codable {
let type: String
let features: [Feature]
init(
type: String,
features: [Feature]
) {
self.type: String, = type
self.features: [Feature] = features
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
type = try container.decodeIfPresent(String.self, forKey: .type)
features = try container.decodeIfPresent([Feature].self, forKey: .features)
}
enum CodingKeys: String, CodingKey {
case type
case features
}
}