Hawk-Eye
Hawk-Eye

Reputation: 400

save JSON as a string in core data

I am fetching data from URL. Data is coming in JSON form. I want to save that JSON as a string in Core Data. How can i do that ? (My JSON is a NSDictionary object and after running it is saying that

Terminating app due to uncaught exception 'NSInvalidArgumentException',reason:'Unacceptable type of value for attribute: property = "cat_list"; desired type =    NSString; given type = __NSCFDictionary;

Upvotes: 2

Views: 2147

Answers (5)

Sethmr
Sethmr

Reputation: 3074

Run the function testThis() to see it all happen. self.user.jsonTest is a Core Data varaible of type Transformable. Replace it with any Transformable CoreData variable and the storeJSON and retrieve JSON should work. I am using swiftyJSON, but it should be extremely easy to remove that if you don't use it.

func testThis() {
    makeFakeData() {
        self.retrieveJSON(self.user.jsonTest) {
            json in
            print("json: \(json)")
        }
    }
}

func storeJSON(dataToStore: [String: AnyObject], completion: (data: NSData?) -> Void) {
    do {
        let data = try NSJSONSerialization.dataWithJSONObject(dataToStore, options: [])
        completion(data: data)
    } catch let error as NSError {
        print("NSJSONSerialization Error: \(error)")
        completion(data: nil)
    }
}

func retrieveJSON(dataToGet: NSObject?, completion: (json: JSON?) -> Void) {
    if let data = dataToGet as? NSData {
        do {
            let nsJSON = try NSJSONSerialization.JSONObjectWithData(data, options: [])
            completion(json: JSON(nsJSON))
        } catch let error as NSError {
            print("NSJSONSerialization Error: \(error)")
            completion(json: nil)
        }
    }
}

func makeFakeData(completion: () -> Void) {
    var solarResourceDic: [String: String] = [:]
    var srDics: [[String: String]!] = []

    for i in 0..<5 {
        solarResourceDic = [:]
        solarResourceDic["system_capacity"] = "\(i)"
        solarResourceDic["azimuth"] = "\(i + 1)"
        solarResourceDic["tilt"] = "\(i + 2)"
        solarResourceDic["array_type"] = "\(i + 3)"
        solarResourceDic["module_type"] = "\(i + 4)"
        solarResourceDic["losses"] = "\(i + 5)"
        srDics.append(solarResourceDic)
    }
    let dic = ["Solar Resource": srDics]

    storeJSON(dic) {
        data in
        self.user.jsonTest = data
        appDelegate.coreData.saveContext()
    }
    completion()
}

Upvotes: 0

Wim Fikkert
Wim Fikkert

Reputation: 106

Please note that the JSON specifications state that the order of keys is not fixed. The result is that the keys will be mingled from time to time which makes retrieving the JSON object impossible using predicates. I had this issue after using NSJsonSerialization to generate an NSString for storing/retrieving in Core Data: the order of the keys was different every time so that I could not check if that JSON message already existed.

See also https://stackoverflow.com/a/15125704/876903.

I decided to create a NSDictionary category that put all keys and values in an ordered array recursively which was then used to see if the NSDictionary object stored along with these NSStrings in the core data object was already stored.

My core data object thus contained:

  • keys (sorted NSString)
  • values (sorted NSString)
  • message (Transformable NSDictionary)

I would use a predicate to see if the JSON object existed like so:

[NSPredicate predicateWithFormat:@"(keys == %@) AND (values == %@)", sortedKeys, sortedValues];

Upvotes: 0

Rakesh
Rakesh

Reputation: 3399

You can give the type of the attribute in your core data model as Transformable and then directly pass the NSDictionary object to it.

If you are creating a NSManagedObject subclass to handle the objects, the attribute will come as type id in your subclass(you can optionally change it to NSDictionary to use the dictionary functions on the object directly when accessing it later).

Note: this is an alternate solution and doesn't convert the dictionary object into string.

Upvotes: 1

Midhun MP
Midhun MP

Reputation: 107121

You need to convert your data to string and store it to your core data.

Like this:

NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

Now save jsonString to core data.

Upvotes: 1

Prajwal Rauniyar
Prajwal Rauniyar

Reputation: 136

Use https://github.com/stig/json-framework/ , and the for you dictionary use

NSString* jsonString = [jsonDict JSONRepresentation];

as core data expects NSString and not a NSDictionary.

Upvotes: 1

Related Questions