I'm trying to use swift 4 to parse a local json file:
{
"success": true,
"lastId": null,
"hasMore": false,
"foundEndpoint": "https://endpoint",
"error": null
}
This is the function I'm using:
func loadLocalJSON() {
if let path = Bundle.main.path(forResource: "localJSON", ofType: "json") {
let url = URL(fileURLWithPath: path)
do {
let data = try Data(contentsOf: url)
let colors = try JSONDecoder().decode([String: Any].self, from: data)
print(colors)
}
catch { print("Local JSON not loaded")}
}
}
}
but I keep getting the error:
Fatal error: Dictionary does not conform to Decodable because Any does not conform to Decodable.
I tried using the "AnyDecodable" approach on this stackoverflow page: How to decode a property with type of JSON dictionary in Swift 4 decodable protocol
but it jumps to the 'catch' statement: catch { print("Local JSON not loaded")
when being used. Does anyone know how to parse this JSON data in Swift 4?
Maybe you are misunderstanding how Codable
works. It's based on concrete types. Any
is not supported.
In your case you might create a struct like
struct Something: Decodable {
let success : Bool
let lastId : Int?
let hasMore: Bool
let foundEndpoint: URL
let error: String?
}
And decode the JSON
func loadLocalJSON() {
let url = Bundle.main.url(forResource: "localJSON", withExtension: "json")!
let data = try! Data(contentsOf: url)
let colors = try! JSONDecoder().decode(Something.self, from: data)
print(colors)
}
Any crash will reveal a design error. The sense of using null
in a file in the main bundle is another question.
I used quicktype to generate Codables and marshaling code:
https://app.quicktype.io?gist=02c8b82add3ced7bb419f01d3a94019f&l=swift
I gave it an array of samples based on your sample data:
[
{
"success": true,
"lastId": null,
"hasMore": false,
"foundEndpoint": "https://endpoint",
"error": null
},
{
"success": true,
"lastId": 123,
"hasMore": false,
"foundEndpoint": "https://endpoint",
"error": "some error"
}
]
This tells quicktype to assume that the null
values in your first sample are sometimes Int
and String
– you can change these if they aren't the possible types. The resulting Codable generated is:
struct Local: Codable {
let success: Bool
let lastID: Int?
let hasMore: Bool
let foundEndpoint: String
let error: String?
enum CodingKeys: String, CodingKey {
case success
case lastID = "lastId"
case hasMore, foundEndpoint, error
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With