#arrays #json #swift #parsing #codable
Вопрос:
Новичок в разработке iOS и имел большой успех, узнав ранее о представлениях и анимации. Тем не менее, у меня возникли проблемы с тем, как проанализировать мой JSON. Моя главная цель-иметь параметры для стихов и глав и возвращаемую строку. Я провел целый день, изучая сопоставление словарей Swift, но решил, что кодируемое сопоставление-более простой метод.
Проблема 1
Достаю Библию.self из данных отлично работает (я могу распечатать все), но пытаюсь расшифровать [главы].self и [Стихи].self приводит к нулю, и, следовательно, к ошибке перехвата. Почему это так?
Проблема 2
Поля JSON главы и стиха являются строками, может ли это вызвать проблемы позже, например, при извлечении нескольких стихов? Я знаю, что есть много полезных инструментов JSON для изменения этих строк на int, если это так. В противном случае я надеюсь, что «Хэшируемый» может сработать.
Проблема 3
Моя самая большая проблема связана с моим выводом JSONOUT. Я считаю, что мне нужна петля внутри петли (глава / стих). Есть ли более простой способ получить определенные строки в JSON?
Код JSON (фрагмент кода):
{
"book": "Jude",
"chapters": [
{
"chapter": "1",
"verses": [
{
"verse": "1",
"text": "Jude, the servant of Jesus Christ, and brother of James, to them that are sanctified by God the Father, and preserved in Jesus Christ, and called:"
},
{
"verse": "2",
"text": "Mercy unto you, and peace, and love, be multiplied."
},
{
"verse": "3",
"text": "Beloved, when I gave all diligence to write unto you of the common salvation, it was needful for me to write unto you, and exhort you that ye should earnestly contend for the faith which was once delivered unto the saints."
}]}]} //it continues on...
Мои структуры
struct Bible : Codable, Hashable {
let book : String
let chapters : [Chapters]
}
struct Chapters : Codable, Hashable {
let chapter : String
let verses : [Verses]
}
struct Verses : Codable, Hashable {
let verse : String
let text : String
}
Мой Код
func readJSONFromFile(fileName: String, getChapters: String, getVerses: String) -> String
{
var JSONoutput: String = ""
guard let path = Bundle.main.path(forResource: fileName, ofType: "json") else {return ""}
let url = URL(fileURLWithPath: path)
guard let data = try? Data(contentsOf: url, options: .mappedIfSafe) else {return ""}
do {
let decoder = JSONDecoder()
let bible = try decoder.decode(Bible.self, from: data)
// the following give erros...
// let chapters = try decoder.decode([Chapters].self, from: data)
// let verses = try decoder.decode([Verses].self, from: data)
// return:
// JSONoutput = for x in BLANK {} ...
}
catch
{
print("error in parsing")
}
return JSONoutput
}
Комментарии:
1. Удалите те строки, которые уже сохранены в объекте верхнего уровня. Вы можете напрямую получить доступ к главе и стихам следующим образом: печать(библия.главы) // печать всех глав печать(библия.главы.первые?.стихи) // печать всех стихов в главе 1
2. Проблема 1: Структура вашего JSON совпадает
Bible
со структурой , поэтому вам нужно ее декодироватьBible
. Декодер JSON не будет автоматически извлекать вложенные объекты (например,Verse
объект) из данных JSON и декодировать их в эти типы. Вы должны сделать это сами.3. @JoakimDanielson Объясни, почему.
4. Вы неправильно поняли то, что я сказал. Я имел в виду, что вы не можете напрямую декодировать
[Verse]
данные JSON с помощью JSONDecoder, если[Verse]
они вложены в другой объект. Например, посмотрите на исходный пост:verses = try decoder.decode([Verses].self, from: data)
. Это не работает.
Ответ №1:
Объект Библии, который вы получите при расшифровке, будет содержать все главы и стихи, поэтому вам не нужно будет расшифровывать что-либо еще.
Вы можете изменить функцию декодирования следующим образом
func readJSONFromFile(fileName: String) -> Bible? {
guard let path = Bundle.main.path(forResource: fileName, ofType: "json") else { return nil }
let url = URL(fileURLWithPath: path)
guard let data = try? Data(contentsOf: url, options: .mappedIfSafe) else { return nil }
do {
return try JSONDecoder().decode(Bible.self, from: data)
} catch {
print("error in parsing: (error)")
return nil
}
}