Как разобрать конкретный файл JSON в SwiftUI

avatar
MohAliBou
9 августа 2021 в 02:47
135
2
0

Допустим, я пытаюсь разобрать этот конкретный файл JSON с помощью SwiftUI:

data.json

[
    {
        "number": 1,
        "word": "hello",
        "sentence": {
            "word_one": "my",
            "word_two": "name"
            "word_three": "is"
            "word_four": "jeff"
        }
    },
    {
        "number": 2,
        "word": "there",
        "sentence": {
            "word_one": "i",
            "word_two": "dream"
            "word_three": "about"
            "word_four": "cheese"
        }
    }
]

Я понимаю, как анализировать number и word, но у меня проблемы с тем, как анализировать все в sentence. Я новичок в программировании для iOS, и ресурсы, на которые я смотрел, меня сбивают с толку. Это код, который у меня есть до сих пор:

struct Content: Codable, Hashable {
    let number: Int
    let word: String
}

struct ContentView: View {
    func jsonParse() -> [Content] {
            let url = Bundle.main.url(forResource: "data", withExtension: "json")!
            let data = try! Data(contentsOf: url)
            let decoder = JSONDecoder()
            let products = try? decoder.decode([Content].self, from: data)
            return products!
        }
    
    var body: some View {
        NavigationView {
            List {
                ForEach(jsonParse(), id: \.self) { content in
                    VStack(alignment: .leading, spacing: 0) {
                        Text("\(content.word)")
                    }
                }
            }
        }
    }
}

Спасибо за помощь!

Источник
El Tomato
9 августа 2021 в 03:00
1

Ваши данные JSON содержат два словаря, которые не являются числовыми и словесными.

MohAliBou
9 августа 2021 в 03:10
0

@ElTomato Я что-то не так делаю со своей структурой?

Paulw11
9 августа 2021 в 03:13
0

Вы можете объявить sentence как словарь [String:String]

MohAliBou
9 августа 2021 в 03:18
0

@Paulw11Paulw11 Как мне тогда создать текст с sentence на ContentView? Будет ли это что-то вроде Text("\(content.sentence.word_one)")?

Paulw11
9 августа 2021 в 03:52
0

Нет, вам нужно будет получить keys словаря и отсортировать массив, а затем перебрать отсортированный массив для ключей и получить доступ к значению for key in dictionary.keys.sorted { Text(dictionary[key]); Я бы поставил ключи и сортировку за вычисляемой переменной в вашей модели и использовал ForEach

El Tomato
9 августа 2021 в 04:15
0

Ваши данные JSON недействительны.

MohAliBou
9 августа 2021 в 04:17
0

@ElTomato Как мне его изменить?

Ответы (2)

avatar
Yotzin Castrejon
9 августа 2021 в 18:52
0

Привет, El Tomato указал, что ваш JSON недействителен. Я использовал фиксированный JSON, предоставленный El Tomato.

Если вам просто нужен ответ, вот он.

import SwiftUI

struct ContentView: View {
    let json = """
[
    {
        "number": 1,
        "word": "hello",
        "sentence": {
            "word_one": "my",
            "word_two": "name",
            "word_three": "is",
            "word_four": "jeff"
        }
    },
    {
        "number": 2,
        "word": "there",
        "sentence": {
            "word_one": "i",
            "word_two": "dream",
            "word_three": "about",
            "word_four": "cheese"
        }
    }
]
""".data(using: .utf8)!
    var body: some View {
        Text("Hello, world!")
            .padding()
            .onAppear(perform: decode)
    }
    
    func decode() {
        let decoder = JSONDecoder()
        
        do {
            let result = try decoder.decode(Content.self, from: json)
            print(result)
        } catch {
            print(error)
        }
        
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

// MARK: - ContentElement
struct ContentElement: Codable {
    let number: Int
    let word: String
    let sentence: Sentence
}

// MARK: - Sentence
struct Sentence: Codable {
    let wordOne, wordTwo, wordThree, wordFour: String
    
    enum CodingKeys: String, CodingKey {
        case wordOne = "word_one"
        case wordTwo = "word_two"
        case wordThree = "word_three"
        case wordFour = "word_four"
    }
}

typealias Content = [ContentElement]

Я использую программу под названием quicktype, и она предварительно заполняет структуры, которые вам понадобятся для декодирования JSON. Прошу прощения, я не могу больше объяснять, потому что я тоже не знаю.

avatar
El Tomato
9 августа 2021 в 04:29
1

Во-первых, ваши данные JSON недействительны. Должно быть следующее.

[
    {
        "number": 1,
        "word": "hello",
        "sentence": {
            "word_one": "my",
            "word_two": "name",
            "word_three": "is",
            "word_four": "jeff"
        }
    },
    {
        "number": 2,
        "word": "there",
        "sentence": {
            "word_one": "i",
            "word_two": "dream",
            "word_three": "about",
            "word_four": "cheese"
        }
    }
]

№. 2, прочитайте свои данные следующим образом.

import UIKit

struct Content: Decodable {
    let number: Int
    let word: String
    let sentence: Sentence
}

struct Sentence: Decodable {
    let word_one: String
    let word_two: String
    let word_three: String
    let word_four: String
}

Наконец, прочитайте файл JSON в комплекте следующим образом.

if let path = Bundle.main.path(forResource: "jsonData14", ofType: "json") {
   if let jsonData = readFileContent(path: path) {
      do {
         let result = try JSONDecoder().decode([Content].self, from: jsonData)
         print(result)
         
         } catch let error as NSError {
         print("\(error)")
      }
   }
}