Home > Mobile >  Trying to update local json file
Trying to update local json file

Time:08-12

To start off, I want to say that I am new to using JSON, so if this code needs some cleanup also, let me know. So I am trying to update json file. I have created an empty jsonfile named data.json in my project, inside a folder I named Data. The file looks like this:

{
    "fullname": "Testuser2",
    "answered": 0,
    "correct": 0
}

This is my JSONData.swift:

import Foundation

struct UserData: Codable {
    let fullname: String
    let answered: Int
    let correct: Int
}

struct GlobalVariable{
    static var fullname = String()
    static var answered = Int()
    static var correct = Int()
}

These function to read the json file:

private func readLocalFile(forName name: String) -> Data? {
        do {
            if let bundlePath = Bundle.main.path(forResource: name,
                                                 ofType: "json"),
                let jsonData = try String(contentsOfFile: bundlePath).data(using: .utf8) {
                return jsonData
            }
        } catch {
            print(error)
        }
        return nil
    }
    
    private func parse(jsonData: Data) {
        do {
            let decodedData = try JSONDecoder().decode(UserData.self,
                                                       from: jsonData)
            GlobalVariable.fullname = decodedData.fullname
            GlobalVariable.answered = decodedData.answered
            GlobalVariable.correct = decodedData.correct
        } catch {
            print("decode error")
        }
    }

And this is how I use it:

func getJSON() {
        
        if let localData = self.readLocalFile(forName: "data") {
            self.parse(jsonData: localData)
            
            print(GlobalVariable.fullname)
            print(GlobalVariable.answered)
            print(GlobalVariable.correct)
            
        }
    }

So the getJSON successfully shows me the correct values.

Now after the GlobalVariable.answered and GlobalVariable.correct has been incrementet, I want to save it.

This is the code I am trying to use to save it:

func saveJSON {
        
        print("---------")
        print(GlobalVariable.fullname)
        print(GlobalVariable.answered)
        print(GlobalVariable.correct)
        print("---------")
        
        
        let dataToUpdate = [UserData(fullname: GlobalVariable.fullname, answered: GlobalVariable.answered, correct: GlobalVariable.correct)]

        do {
            let jsonData = try JSONEncoder().encode(dataToUpdate)
            let jsonString = String(data: jsonData, encoding: .utf8)!
            print(jsonString)
            
            if let documentDirectory = FileManager.default.urls(for: .documentDirectory,
                                                                in: .userDomainMask).first {
                let pathWithFilename = documentDirectory.appendingPathComponent("data.json")
                do {
                    try jsonString.write(to: pathWithFilename,
                                         atomically: true,
                                         encoding: .utf8)
                } catch {
                    // Handle error
                }
            }
            
        } catch { print(error) }
    }

The three print codes inside saveJSON shows the correct value, but someone nothing gets saved to the json file. The json file stays untouched.. How come?

I've also tried removing the .json from let pathWithFilename = documentDirectory.appendingPathComponent("data.json"), but still not working..

CodePudding user response:

You are starting with your data.json in your bundle.

You read that, change the values, and then write it to Documents folder.

So, when you want to read the file, you need to first see if it exists in the Documents folder. If so, read it from there. If it doesn't exist (e.g. first time the app is run), then read it from the bundle.

CodePudding user response:

you can read from the local file in the main bundle but you couldn't write on it,

get documents folder:
private func documentsFolder() -> String {
    let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
    let documentDirectory = paths[0] as String
    return documentDirectory
}

// load data code

 private mutating func loadData() {
    
    let filePath = documentsFolder().appending("/filename.data")
    let fileManager = FileManager.default
    if fileManager.fileExists(atPath: filePath) {
        print("FILE AVAILABLE")
        lists = load()
    } else {
        //load json file
        lists = loadFromBundle()
        //saved words list in documents directory
        save(lists ?? [])
    }
}

///loading data from file created in documents directory with name "filename.data"
func load<O:Codable>() -> O? {
    let url = URL(fileURLWithPath: documentsFolder().appending(path.rawValue))
    guard let data = try? Data(contentsOf: url) else { return nil }
    do {
        return try JSONDecoder().decode(O.self, from: data)
    } catch {
        print(error)
    }
    return nil
}

//// initially load from main bundle to get initial values or whatever

private func loadFromBundle() -> [ListModel]? {
    var arr = [ListModel]()
    let url = Bundle.main.url(forResource: "Lists", withExtension: "json")!
    do {
        let data = try Data(contentsOf: url)
        let json = try JSONDecoder().decode([ListModel].self, from: data)
        arr = json
    }
    catch {
        print("Error occured during Parsing", error)
    }
    return arr
}

//// saving data in new file created and this file will be loaded again to read from.

func save<O: Codable>(_ object: O) {
    let url = URL(fileURLWithPath: documentsFolder().appending(path.rawValue))
    guard let data = try? JSONEncoder().encode(object.self) else { return }
    do {
        try data.write(to: url)
        
    } catch {
        print(error)
    }
}
  • Related