问题
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?
回答1:
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.
回答2:
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
}
}
来源:https://stackoverflow.com/questions/49018384/fatal-error-dictionarystring-any-does-not-conform-to-decodable-because-any-d