I have a JSON file containing around 3000 unique id codes of the following format (10 digits):
1012111000
I am currently importing it into a simple struct of the following format:
struct Codes: Codable, Identifiable {
let id: String
}
using the following extension:
extension Bundle {
func decode<T: Codable>( file: String) -> T {
guard let url = self.url(forResource: file, withExtension: nil) else {
fatalError("Failred to locate \(file) in bundle")
}
guard let data = try? Data(contentsOf: url) else {
fatalError("Failred to load \(file) from bundle")
}
let decoder = JSONDecoder()
guard let loaded = try? decoder.decode(T.self, from: data) else {
fatalError("Failed to decode \(file) from bundle")
}
return loaded
}
}
and call
let code: [Codes] = Bundle.main.decode(file: "codes.json")
This works as expected and the data is available in Swift.
But.
The id code is actually made up of 4 individual codes. The first 3 characters are one 3-digit code, the 4th character is another single-digit code, the 5th and 6th characters form a third 2-digit code and the last four characters form a final 4-digit code. As such I'd like to instead import into a struct as follows: Note in this that id4 is unique but id1, id2 and id3 will have duplicates.
struct Codes: Codable, Identifiable {
let id1: String // 1st-3rd character (3 digits)
let id2: String // 4th character (1 digit)
let id3: String // 5th-6th character (2 digits)
let id4: String // 7th-10th characters (4 digits)
}
Any advice on how to achieve this in a nice neat way would be appreciated. I know there are numerous ways of parsing strings but I'm not sure how best to acomplish this within a loop. I should also note that the decoder is generic due to it needing to import a number of other (simpler) JSONs and this functionality needs to remain.
best, Sy
to make "Codes" compatible with what you already have and have the component ids, try this approach, or something similar:
struct Codes: Codable, Identifiable {
let id: String
func id1() -> String { string(from: 0, to: 3) }
func id2() -> String { string(from: 3, to: 4) }
func id3() -> String { string(from: 5, to: 7) }
func id4() -> String { string(from: 6, to: 10) }
// or using lazy var
// lazy var id1: String = { string(from: 0, to: 3) }()
// lazy var id2: String = { string(from: 3, to: 4) }()
// lazy var id3: String = { string(from: 5, to: 7) }()
// lazy var id4: String = { string(from: 6, to: 10) }()
private func string(from: Int, to: Int) -> String {
let start = id.index(id.startIndex, offsetBy: from)
let end = id.index(id.startIndex, offsetBy: to)
return String(id[start..<end])
}
}
Note, when using lazy var you need to declare:
var code = Codes(id: "1012111000")
not
let code = Codes(id: "1012111000")
as with the functions.