WWDC24 SALE: Save 50% on all my Swift books and bundles! >>

SOLVED: Is it possible to use a variable String to read a JSON file?

Forums > SwiftUI

Dear kind people- I have multiple JSON files, but would like to read a specific JSON file when user selects from a list (.i.e., Picker). Is this possible and if so how might it be done. The reason for loading only one JSON at a time is due to the large number and sizes of the JSON files. I have tried many permuations to pass fileName to the following code "var datas: [Data] = load(fileName)". But all have failed.

-Thank you.

1      

Yep, it can be done easily. But we need to see more of your code to figure out the best way to assist you.

2      

Steve would like someone to code for him, or would prefer learning some techniques. It's hard to tell....

I have tried many permutations to pass fileName to the following code "var datas: [Data] = load(fileName)". But all have failed.

It would be easier to help you learn how to code SwiftUI and read data from JSON files, if you provide some code!

Please amend your query above. Add one or two of your permutations. Add some comments to your code so we can see what you clearly understand, and where your knowledge gap may be. Help us help you!

1      

//
//  ContentView.swift
//  TestJSON
//
//  Created by Sharpy on 2/15/23.
//
import SwiftUI

let shortNames = ["HFC227EA.JSON", "TCE1112.JSON", "F134A.JSON", "HCFC142B.JSON", "TCE111.JSON", "TFACTONE.JSON", "R143A.JSON"]

public var fileName = "HFC227EA.JSON"

struct ContentView: View {

    @State var foundName = "HFC227EA.JSON"

    var body: some View {
        NavigationView {
            VStack(alignment: .leading) {

                List {

                    Picker("Select short name: ", selection: $foundName) {
                        ForEach(shortNames, id: \.self) {
                            Text($0)
                            var specs: [Spec] = load(foundName)
                        }
                    }
// Code here to display information and graph data in JSON file selected by uesr
                }
            }
        }
    }
}

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

func load<T: Decodable>(_ fileName: String) -> T {
    let data: Data

    guard let file = Bundle.main.url(forResource: fileName, withExtension: nil)
        else {
            fatalError("Couldn't find \(fileName) in main bundle.")
    }

    do {
        data = try Data(contentsOf: file)
    } catch {
        fatalError("Couldn't load \(fileName) from main bundle:\n\(error)")
    }

    do {
        let decoder = JSONDecoder()
        return try decoder.decode(T.self, from: data)
    } catch {
        fatalError("Couldn't parse \(fileName) as \(T.self):\n\(error)")
    }
}

1      

Above code gives error "Variable 'specs' was never used; consider replacing with '' or removing it." Unable to correctly update fileName so that program loads user selected JSON file. I am relatively new to SwiftUI and trying to wrap my head around Declarative coding. Thank you for taking time to review!

1      

Steve we encourage you to explore the many lessons that @twoStraws has provided for reading JSON from your application's bundle. Here's an example where I modified code allowing a user to select one of three files stored in the bundle.

struct JSONSelectorView: View {
    // These are the choices you give your user.
    private var dataFiles = ["Swift", "Beatles", "Wham!"]
    @State private var selectedFile = "Swift" // <-- This is the user's selection.

    @State private var albums = [Album]()  // empty

    // This calculates the NAME of the json file
    private var fullFileName: String { selectedFile + ".json" }

    var body: some View {
        VStack {
            // This presents the options to your user.
            Picker("Select:", selection: $selectedFile) {
                ForEach(dataFiles, id:\.self) {
                    fileName in Text("\(fileName)")
                }
            }.padding(.vertical)
            // This displays the contents of the JSON file
            VStack (alignment: .leading) {
                ForEach(albums) { album in
                    ForEach(album.songs) { song in
                        Text("\(album.albumName): \(song.songName)")
                    }
                }
            }
        }.padding()
        .onChange(of: selectedFile) { _ in
            // When the user changes their SELECTED FILE,
            // load a DIFFERENT json file from the bundle.
            albums = Bundle.main.decode([Album].self, from: fullFileName)
        }
    }
}

// Here's a sample struct for an album. Your json file should reflect this structure
struct Album: Codable, Identifiable {
    var albumName: String
    var songs: [Song]
    var id: String { albumName }

    struct Song: Codable, Identifiable {
        var songName: String
        var id: String { songName }
    }
}

Here's a sample file containing Album data. Name this file Beatles.json and drop it in your bundle.

[
    {
    "albumName": "Let it Be",
    "songs": [
        { "songName": "The Long and Winding Road" },
        { "songName": "Get Back"                  },
        { "songName": "Let It Be"                 },
        { "songName": "Maggie Mae"                }
    ]
    },
    {
    "albumName": "Abbey Road",
    "songs": [
        { "songName": "Something"          },
        { "songName": "Because"            },
        { "songName": "Mean Mr Mustard"    }
    ]
    },
    {
    "albumName": "Please, Please Me",
    "songs": [
        { "songName": "There's A Place"     },
        { "songName": "Love Me Do"          },
        { "songName": "Please Please Me"    }
    ]
    }
]

1      

Thank you so much Obelix. I have gone through many of Paul Hudson's 100 days of Switui lessons and payed for several of his downloads. Still, there are many things about Swiftui that vex me. I will keep plugging away.

1      

Save 50% in my WWDC sale.

SAVE 50% To celebrate WWDC24, all our books and bundles are half price, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.

Save 50% on all our books and bundles!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.