Ошибка при попытке распарсить JSON: No value associated with key CodingKeys

swift5
swiftui

#1

Доброго времени суток!

Столкнулся с ошибкой при попытке распарсить JSON: Xcode ругается на CodingKeys.

JSON выглядит так

[
{
“name”: “Алексей”,
“surname”: “Алексеев”,
“middleName”: “Алексеевич”
},
{
“name”: “Иван”,
“surname”: “Иванов”,
“middleName”: “Иванович”
}
]

Модель данных

struct UserInfo: Codable, Identifiable {
var id = UUID()
let name: String
let surname: String
let middleName: String
}

Попытка распирсить JSON

do {
let decodeResponse = try JSONDecoder().decode([UserInfo].self , from: data!)
completion(decodeResponse)
} catch {
print(error)
}

Описание ошибки в блоке catch:
keyNotFound(CodingKeys(stringValue: “id”, intValue: nil), Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: “Index 0”, intValue: 0)], debugDescription: “No value associated with key CodingKeys(stringValue: “id”, intValue: nil) (“id”).”, underlyingError: nil))

Ошибка появляется после подписания модели данных на протокол Identifiable. Если не модель не подписывать под протокол, то получаемые данные декодируются корректно.
В чем может быть проблема?
Интрефейс пишу на SwiftUI, результат хочу поместить в List.


#2
let jsonData = """
    [
        {
            "name": "Алексей",
            "surname": "Алексеев",
            "middleName": "Алексеевич"
        },
        {
            "name": "Иван",
            "surname": "Иванов",
            "middleName": "Иванович"
        }
    ]
""".data(using: .utf8)!

struct UserInfo: Codable, Identifiable {
    // MARK: - Либо id пометьте как let
    var id = UUID()
    let name: String
    let surname: String
    let middleName: String
    
    // MARK: - Либо пропишите ключи
    private enum CodingKeys: String, CodingKey {
        case name, surname, middleName
    }
}


do {
    let decodeResponse = try JSONDecoder().decode([UserInfo].self , from: jsonData)
    print("Response: ", decodeResponse)
} catch {
    print(error)
}

#3

Спасибо за помощь! Прописал ключи и все заработало!
Но можешь объяснить, для чего нужны ключи, если переменные в моей модели называются точно так же, как в JSON? Смотрел несколько видео-уроков и статей по работе с JSON и нигде ключи не используются.


#4

если вы оставите id как var, и не исключите из CodingKeys, то при декодировании у вас будет ошибка что нет такого поля в json, но если пометите как опционал
var id: UUID? = UUID(), то все будет хорошо)
Так понятно?

В случае если вы используете let и сразу назначаете значение, то id больше не мутирует и не будет использовано при декодировании, это предположение)


#5

Да, спасибо за ответ!