I have a struct that I would like to parse from Json:
struct Subsidiary: Decodable {
let id: Int?
let subsidiary_ref: String?
let name: String?
let address: String?
}
I try to parse it like:
let sub: [Subsidiary] = try! JSONDecoder().decode([Subsidiary].self, from: data)
where data is Data type from
session.dataTask(with: urlRequest) { (data, response, error) in
and it gives me an error
Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.typeMismatch(Swift.Array<Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array<Any> but found a string/data instead.", underlyingError: nil))
If I do it like this:
let sub: String = try! JSONDecoder().decode(String.self, from: data)
it works and it gives me son
[
{"id": 5913, "subsidiary_ref": "0000159", "name": "Mercator Hipermarket Koper", "address": "Poslov.98-Koper,Dolinska C", "city": "Koper", "coordinates_x": null, "coordinates_y": null, "phone_number": "+386 56-636-800", "frequency": "A", "channel": "Food", "subchannel": "Hypermarket", "customer": 7, "day_planned": true, "badge_visible": true, "open_call": true, "number_of_planned": 13, "number_of_calls": 22, "last_call_day": 3, "notes": " notesi ki ne smejo nikoli zginiti bla marko bdsa"},
{"id": 5870, "subsidiary_ref": "0000773", "name": "Kompas Shop Pe Ferneti?i", "address": "Partizanska 150", "city": "Se?ana", "coordinates_x": null, "coordinates_y": null, "phone_number": "+386 57-380-636", "frequency": "A", "channel": "Food", "subchannel": "Supermarket", "customer": 17, "day_planned": true, "badge_visible": true, "open_call": true, "number_of_planned": 13, "number_of_calls": 1, "last_call_day": 1, "notes": null},...
]
What is wrong with my code?
I figure out, that if I create a string
variable, and then convert this string value to data it works even with Subsidiary
struct.
So something should be wrong with the data
variable.
The fact that you can decode a String.self
and get your JSON printed means that the root of the JSON is a string. The JSON you got, in text form, probably looks like this:
"[\r\n {\"id\": 5913, \"subsidiary_ref\": \"0000159\", \"name\": \"Mercator Hipermarket Koper\", \"address\": \"Poslov.98-Koper,Dolinska C\", \"city\": \"Koper\", \"coordinates_x\": null, \"coordinates_y\": null, \"phone_number\": \"+386 56-636-800\", \"frequency\": \"A\", \"channel\": \"Food\", \"subchannel\": \"Hypermarket\", \"customer\": 7, \"day_planned\": true, \"badge_visible\": true, \"open_call\": true, \"number_of_planned\": 13, \"number_of_calls\": 22, \"last_call_day\": 3, \"notes\": \" notesi ki ne smejo nikoli zginiti bla marko bdsa\"}\r\n]"
Note that the actual JSON you want is put in ""
s, so all the special characters are escaped.
The web service has given the JSON in a very weird way...
To get the actual JSON data decoded, you need to get the string first, then turn the string into Data
, then decode that Data
again:
// nil handling omitted for brevity
let jsonString = try! JSONDecoder().decode(String.self, from: data)
let jsonData = jsonString.data(using: .utf8)!
let sub = try! JSONDecoder().decode([Subsidiary].self, from: jsonData)
Of course, the best solution is to fix the backend.