Let's say I have a JSON with this data:
[
{ "id": "a",
"x": 1,
"y": 1 },
{ "id": "b",
"x": 7,
"y": 12 },
.
.
.
{etc.}
]
In Swift, I can load that into a struct:
struct jsonDataStruct: Codable, Identifiable {
let id: String
let x: Int
let y: Int
}
But what if, I wanted to calculate the distance between x and y, for example? Normally, I've written a struct with an initializer, like this:
struct coordinates: Identifiable {
let id: String
let x: Int
let y: Int
let length: Int?
init(id: String, x: Int, y: Int) {
self.x = x
self.y = y
self.distance = sqrt(x * x + y * y)
// do other calculations or processing
}
}
And when I create an object:
let dudeWheresMyCar = coordinates(id: "my car", x: 12, y: 18)
print("it's \(dudeWheresMyCar.distance) meters away")
the distance was automatically calculated when the coordinates object was created.
How would I do that with the struct jsonDataStruct above? I've written an initializer for it, yet it doesn't seem to be called when data is loaded from a JSON:
Bundle-Decodable.swift:
import Foundation
extension Bundle {
func decode(_ file: String) -> [jsonDataStruct] {
guard let url = self.url(forResource: file, withExtension: nil) else {
fatalError("Failed to locate \(file) in bundle.")
}
guard let data = try? Data(contentsOf: url) else {
fatalError("Failed to load \(file) from bundle.")
}
let decoder = JSONDecoder()
guard let loaded = try? decoder.decode([jsonDataStruct].self, from: data) else {
fatalError("Failed to decode \(file) from bundle.")
}
return loaded
}
}
ContentView.Swift:
import SwiftUI
struct ContentView: View {
let testJsonData = Bundle.main.decode("testData.json")
var body: some View {
Text("\(testJsonData.count)")
.padding()
}
}
I could simply compute the distance or any other value as needed during runtime, but having it pre-computed means it's ready to be used, and wouldn't have to write additional code.
I'm sure this basic question has been answered before, but being an amateur coder I'm most likely missing it because I probably don't know what to look for, or how to ask the question.
Thank you!
distance(orlength- you have both) is better expressed as a computed property,var distance: Double { sqrt(x * x + y * y) }- this way you don't need to decode it at all. Alternatively, you'd need to write a custominit(from: Decoder)and computedistancethere. Also, it's strongly recommended to follow the Swift convention of Capitalizing type names:struct JsonDataStruct { },struct Coordinates { }