How can I save and then load a JSON in NSUserDefaults with SwiftyJSON?
Asked Answered
S

9

22

in my iOS project I need to save an entire JSON as user data and then reload it on next app launch. Squashing it into many values and then recreate the JSON is not an option, I just need some serializable way of saving the entire raw JSON. I tried to convert it to String by doing json.rawString() and recreate it by passing the obtained string to JSON(string), but it doesn't work.

I'm both astonished by the difficulty of making such a simple thing and by the lack of informations about a thing like this online, so I can not wait to discover how to do that :)

Example:

public func saveJSON(j: JSON) {
    let defaults = NSUserDefaults.standardUserDefaults()
    defaults.setValue(j.rawString()!, forKey: "json")
    // here I save my JSON as a string
}

public func loadJSON() -> JSON {
    let defaults = NSUserDefaults.standardUserDefaults()
    return JSON(defaults.valueForKey("json") as! String))
    // here the returned value doesn't contain a valid JSON
}
Spiritualty answered 3/3, 2016 at 17:59 Comment(4)
Are you sure you want to save it to NSUserDefaults? It might be better to de-serialize your JSON into an array or a dictionary and then save that to a plist in your documents directory and load that on your app launch.Spithead
The problem is that data may change, and anyway it's a very small JSON, so for me it's ok.Spiritualty
Did saveJSON works for you ?Morea
Yes, it worked. But Swift could have changed by now and I didn't try if it works anymore. Does it give you any problem?Spiritualty
S
25

Thank you for your answers but they didn't solve my problem. I finally found the solution, which was really simple in facts:

public func loadJSON() -> JSON {
    let defaults = NSUserDefaults.standardUserDefaults()
    return JSON.parse(defaults.valueForKey("json") as! String))
    // JSON from string must be initialized using .parse()
}

Really simple but not documented well.

Spiritualty answered 5/3, 2016 at 11:20 Comment(0)
B
12

Swift 5+

 func saveJSON(json: JSON, key:String){
   if let jsonString = json.rawString() {
      UserDefaults.standard.setValue(jsonString, forKey: key)
   }
}

    func getJSON(_ key: String)-> JSON? {
    var p = ""
    if let result = UserDefaults.standard.string(forKey: key) {
        p = result
    }
    if p != "" {
        if let json = p.data(using: String.Encoding.utf8, allowLossyConversion: false) {
            do {
                return try JSON(data: json)
            } catch {
                return nil
            }
        } else {
            return nil
        }
    } else {
        return nil
    }
}

Use this if you using SwiftyJSON.

Bronchial answered 12/3, 2018 at 6:29 Comment(1)
Thanks a lot. Works perfectly.Desman
T
2

I used the following code and it works like a charm!

NSString *json = @"{\"person\":{\"first_name\":\"Jim\", \"last_name\":\"Bell\"}} ";
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

if([defaults objectForKey:@"json"]== nil){
    [defaults setObject:json forKey:@"json"];
    //[defaults synchronize];
}
else{
    NSLog(@"JSON %@", [defaults objectForKey:@"json"]);
}

First try to see whether you can save a hard-coded string to the NSUserDefaults first.

Also try to call a [defaults synchronize]; call when you want to save the data. Although that is NOT required, it might be needed in extreme conditions such as if the app is about to terminate.

Tortola answered 3/3, 2016 at 18:34 Comment(0)
B
2

to retrieve from UserDefaults

func get(_ key: String)-> JSON? {
    
    if let standard = UserDefaults.standard.data(forKey: key), let data = try? standard.toData() {
        return JSON(data)
    } else {
        return nil
    }
}

You should parse everything to Data, in order to save model (Better from JSON / JSONSerialization) to UserDefaults

Coded In Swift 5.x

Boggess answered 14/7, 2020 at 12:1 Comment(0)
P
1

Swift 4+

A cleaner version to the one provided by Alfi up above, for any else that might need this.

func addUserJSONDataToUserDefaults(userData: JSON) {
    guard let jsonString = userData.rawString() else { return }
    userDefaults.set(jsonString, forKey: "user")
}

func getCachedUserJSONData() -> JSON? {
    let jsonString = userDefaults.string(forKey: "user") ?? ""
    guard let jsonData = jsonString.data(using: .utf8, allowLossyConversion: false) else { return nil }
    return try? JSON(data: jsonData)
}
Paleethnology answered 29/8, 2018 at 0:14 Comment(0)
S
0

Here's a swift example that works

import SwiftyJSON
class Users{

    init(){
        let yourJSON = {"name":"Deeznuts"}
        let response = JSON(yourJSON)

        // Store your 
        let httpMessage = response["name"].stringValue 

    }
}
Semitrailer answered 3/3, 2016 at 19:22 Comment(0)
S
0

I extended Userdefaults and added a new var for easy usage and consistency of my keys. Here is my code:

extension UserDefaults {
    var downloadedMarkersInfo : JSON? {
        get {
            if let jsonString = defaults.value(forKey: "markers") as? String {
                if let json = jsonString.data(using: String.Encoding.utf8, allowLossyConversion: false) {
                    return try! JSON(data: json)
                }
            }
            return nil
        }
        set {
            if let json = newValue {
                let jsonString = json.rawString()!
                defaults.setValue(jsonString, forKey: "markers")
            }
        }
    }
}

The usage in my View Controller:

if let jsonData = defaults.downloadedMarkersInfo {
// Your code here.
}
Speroni answered 10/4, 2018 at 22:31 Comment(1)
Please don't use .synchronize(). It's deprecated, useless, and can even create issues like lagging if the defaults domain is big. You do NOT need it to save, it's automatic and done by the system.Lemmy
H
0

Swift 5 method to save and load JSON from UserDefaults (with SwiftyJSON)

extension UserDefaults {
    func setValue( _ json: JSON, forKey key: String ) {
        if let rawString = json.rawString() {
           self.setValue(rawString, forKey: key)
        }
    }
    func json( forKey key: String ) -> JSON? {
        if let text = self.string(forKey: key) {
            return JSON(parseJSON: text)
        } else {
            return nil
        }
    }
}

// Save
var myData: JSON = [0, 1, 2, 3]
UserDefaults.standard.setValue(myData, forKey: "MyKey")

// Load
var myData2 = UserDefaults.standard.json(forKey: "MyKey")
Hayott answered 19/2 at 23:1 Comment(0)
L
-1

using SwiftyJSON - SWIFT 5

    var data = JSON()

    if(CustomDefaults().checkObject(key: "list2")){
        data = JSON.init(parseJSON: CustomDefaults().getObject(key: "list2") as? String ?? "")
    }
    else{
        var bomb = [JSON]()
        bomb.append(["name":"Happy","url":"google.com"])
        let finalData = JSON(bomb).rawString() ?? ""  //data.rawString() ?? ""
        CustomDefaults().setObject(value: finalData, key: "list2")
    }
Lawman answered 15/8, 2017 at 11:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.