Home > other >  How to parse two arrays from local JSON file using swift
How to parse two arrays from local JSON file using swift

Time:09-17

I have a JSON file:

{
    "bookStruct":
    {
        "bookInfo": [
            {
                "name": "Greenlight",
                "genre": "R&B",
                "imagename": "greenlight.png"
            }
        ],
        "bookAudio": [
            {
                "name" : "BigBang",
                "instrument" :"Arp",
                "bookSong" : "bigBang.mp3",
            },
            {
                "name" : "Boolll",
                "instrument" :"Drums",
                "bookSong" : "Boolll.mp3",
            },
            {
                "name" : "Kreker",
                "instrument" :"Drums",
                "bookSong" : "Kreker.mp3",
            }
        ]
    }
}

Need to know, how I can parse this two arrays bookInfo and bookAudio. I've tried something like this, but it parsing only one of the arrays:

struct BookDesc: Decodable {
    let bookStruct: BookStruct
}
    
struct BookStruct: Decodable {
    let bookInfo: [BookInfo]
    let bookAudio: [BookAudio]
}

struct BookAudio: Decodable {
    let name: String
    let instrument: String
    let bookSong: String
}

struct BookInfo: Decodable {
    let name: String
    let genre: String
    let imagename: String
}

var booksCollect = [BookInfo]()

func parseBooks() -> [BookInfo] {
        
    let fileManager = FileManager.default
    let path = Bundle.main.resourcePath
        
    let enumerator:FileManager.DirectoryEnumerator = fileManager.enumerator(atPath: "\(path!)/BooksFolders")!
    while let element = enumerator.nextObject() as? String {
        if element.hasSuffix(".json") { // checks the extension
            print(element)
        }
    }

    var booksNames = [BookInfo]()
            
    guard let urls = Bundle.main.urls(forResourcesWithExtension:".json", subdirectory:nil) else {
        return booksNames
    }

    for url in urls {
        do {
            let bookDesk = try parseLoop(url: url)
            booksNames.append(contentsOf: bookDesk.bookInfo)
        } catch {
            print("\(error) reading \(url)")
        }
    }

    return loopsInfo
}

func parseLoop(url: URL) throws -> BookStruct {
    let jsonData = try Data(contentsOf: url)
    let bookTop = try JSONDecoder().decode(BookDesc.self, from: jsonData)
    return bookTop.bookDesk
}
    
func prepareInit() {
    booksCollect = parseBooks()
    tableView.reloadData()
}

CodePudding user response:

Here is my solution for this. Note that I moved the url handling part to a separate function to make the posted code clearer

var bookInfoCollect = [BookInfo]()
var bookAudioCollect = [BookAudio]()

//...

func parseBooks() -> [BookStruct] {
    let urls = getUrls()

    var books = [BookStruct]()
    for url in urls {
        do {
            let bookDesk = try parseLoop(url: url)
            books.append(bookDesk)
        } catch {
            print(error)
        }
    }

    return books
}

    
func prepareInit() {
    let books = parseBooks()
    bookInfoCollect = books.flatMap(\.bookInfo)
    bookAudioCollect = books.flatMap(\.bookAudio)
    print(bookInfoCollect)
    print(bookAudioCollect)
    //tableView.reloadData()
}
  • Related