Сложность анализа целочисленного значения в JSON с использованием декодера JSON в Swift

Я пытаюсь декодировать некоторый JSON из API, который выглядит так (foo — это короткий список свойств):

{"page":1,"total_results":10000,"total_pages":500,"results":[{"foo":"bar"},{"foo":"bar2"},{"foo":"bar3"}]}

Структура, рекомендованная quicktype.io, которая мне тоже кажется правильной:

struct ObjectsReturned: Codable {
    let page, totalResults, totalPages: Int
    let results: [Result]

    enum CodingKeys: String, CodingKey {
        case page
        case totalResults = "total_results"
        case totalPages = "total_pages"
        case results
    }
}

// MARK: - Result
struct Result: Codable {
    let foo: String
}

Однако, когда я пытаюсь декодировать, хотя он может обрабатывать страницу, он выдает ошибку в total_results следующим образом:

typeMismatch(Swift.Dictionary‹Swift.String, Any›, Swift.DecodingError.Context(codingPath: [_DictionaryCodingKey(stringValue: total_results, intValue: nil)], debugDescription: Ожидается декодирование Dictionary‹String, Any›, но вместо этого найдено число ., основная ошибка: ноль))

В чем может быть причина этой ошибки и как ее исправить?

Спасибо за любые предложения.

Примечание:

Декодирование осуществляется через:

do {
                            let mything = try JSONDecoder().decode([String:ObjectReturned].self, from: data)
                        } catch {
                            print(error)
                        }

person user6631314    schedule 28.07.2020    source источник
comment
Это правильный json? Если это так, вы должны называть decode как decode(ObjectReturned.self, from: data)   -  person Joakim Danielson    schedule 28.07.2020


Ответы (2)


Вы пытаетесь декодировать неправильный тип. Ваш корневой объект — это отдельный экземпляр ObjectsReturned, а не экземпляр [String:ObjectsReturned].

let mything = try JSONDecoder().decode(ObjectsReturned.self, from: json2)
person Dávid Pásztor    schedule 28.07.2020
comment
Вот оно. Спасибо! - person user6631314; 28.07.2020

Сама ошибка очень ясна, она говорит, что вы пытаетесь декодировать Dictionary, но JSONDecoder не может его найти. Вы, вероятно, скопировали этот код откуда-то еще, и, вероятно, это причина этой ошибки. Вы должны быть в состоянии определить модель, просто взглянув на нее. Здесь вы можете видеть, что в начале нет ключа, значение которого равно ожидаемому ObjectReturned. Если JSON было:

{"someStringKey":{"page":1,"total_results":10000,"total_pages":500,"results":[{"foo":"bar"},{"foo":"bar2"},{"foo":"bar3"}]}}

ваша расшифровка должна была сработать. Вместо этого в вашем случае JSON не имеет ведущего ключа, как в приведенном выше примере "someStringKey", поэтому вам просто нужно:

do {
    let mything = try JSONDecoder().decode(ObjectsReturned.self, from: data)
    print(mything)
} catch {
    print(error)
}

Всегда лучше вставить JSON в Quicktype и сгенерировать оттуда модель структуры для декодирования. Надеюсь, это поможет с любыми трудностями, связанными с JSON декодированием.

person Frankenstein    schedule 28.07.2020
comment
Спасибо! Проголосовал за ваш подробный ответ за объяснение, так как я уже принял другой. У быстрого типа был правильный код декодера JSON. Да, я, должно быть, скопировал код для разбора другого API в предложенном вами формате и изменил имя объекта, не изменив остальную часть. - person user6631314; 28.07.2020
comment
Пожалуйста. Это была распространенная ошибка из-за невнимательности. В любом случае удачного кодирования :) - person Frankenstein; 28.07.2020
comment
Quicktype великолепен, но иногда он генерирует много вспомогательных классов. Вы пытаетесь улучшить его, когда это происходит? stackoverflow .com/questions/63138535/ - person user6631314; 28.07.2020