I've got a problem with parsing data from the server. I've got JSON which has an array of objects, something like this:
{
"items": [
{
"itemType": {
"id": 12,
"tagId": "FCHA78558D"
},
"parts": [
{
"partId": 52,
"manufacturer": "xxx"
},
{
"partId": 53,
"manufacturer": "xxx"
},
{
"partId": 54,
"manufacturer": "xxx"
}
],
"description": "yyy"
},
{
"itemType": {
"id": 13,
"tagId": "FCHA755158D"
},
"parts": [
{
"partId": 64,
"manufacturer": "xxx"
},
{
"partId": 65,
"manufacturer": "xxx"
}
],
"description": "zzz"
}
]
}
I only want to obtain this one array of objects so I implemented this class like this:
class User : Object, Decodable {
var items = List<Equipment>()
}
in the Alamofire I'm downloading the JSON, parsing it to data and then in do-catch block I receive an error:
let items = try JSONDecoder().decode(User.self, from: receivedValue)
error:
▿ DecodingError
▿ typeMismatch : 2 elements
- .0 : Swift.Array<Any>
▿ .1 : Context
▿ codingPath : 2 elements
- 0 : CodingKeys(stringValue: "items", intValue: nil)
▿ 1 : _JSONKey(stringValue: "Index 0", intValue: 0)
- stringValue : "Index 0"
▿ intValue : Optional<Int>
- some : 0
- debugDescription : "Expected to decode Array<Any> but found a dictionary instead."
- underlyingError : nil
That's weird because it is an array of objects for sure. I tried setting my items property to String to see the result and then I got:
- debugDescription : "Expected to decode String but found an array instead."
I had this error couple of times but I always managed to find the solution.
I suppose you were using the List
conditional conformance to Decodable
from my answer to your previous question. I don't fully understand why it doesn't work in this specific case, but I'll investigate.
Until then, you can make decoding work by manually implementing the init(from decoder:Decoder)
function.
class User : Object, Decodable {
let items = List<Equipment>()
private enum CodingKeys: String, CodingKey {
case items
}
required convenience init(from decoder:Decoder) throws {
self.init()
let container = try decoder.container(keyedBy: CodingKeys.self)
let itemsArray = try container.decode([Equipment].self, forKey: .items)
self.items.append(objectsIn: itemsArray)
}
}