Write JSON Response to .plist File
Asked Answered
T

6

10

Frustration on the Top !!!

I am getting some JSON Response from the Service and I want to store it in the .plist file for Future Reference. I am unable to save my JSON Response to .plist File. I think it's due to some null values into the Response.

Note : I confirmed that the Response is in JSON Format using jsonparser.


My Code :

NSError *error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSDictionary *dictResult = [(NSDictionary*)json objectForKey:@"myKey"];
NSLog(@"Result Dictionary :: %@",dictResult);

NSURL *cacheDir = [[[NSFileManager defaultManager] URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] lastObject];
NSURL *path = [cacheDir URLByAppendingPathComponent:@"FinalResult.plist"];
NSLog(@"Path :: %@",path);

BOOL success = [dictResult writeToURL:path atomically:YES];
NSLog(@"success? %d", success);

Note : I got all the NSLog Values (means the Response Dictionary and File Path but 0 for success).


Problem : There are almost 70-80 key-value pairs in the Response and I don't want to remove/replace all the null values. Because What I want is ...

  1. GET the Response From the Server.
  2. Fill all the UITextFields with the Response.
  3. POST the Same Response to the Server with some Edited Values from the UITextFields.

So, I just want to change the Edited UITextField values in the Object and let it POST to the Server.

What is the Optimum Way to Fix this ?

Tercel answered 20/3, 2013 at 14:17 Comment(2)
What types of data does the JSON dictionary contain? Strings, numbers, anything else? Can you add the JSON to your question?Agnew
@TomHarrington: My JSON Dictionary contains almost all types of values , you mentioned in your Answer.Tercel
A
16

I bet that your JSON contains at least one null value.

When you have JSON that contains null and you convert it using NSJSONSerialization, the null is replaced by an instance of NSNull. If your dictionary contains NSNull, then writeToURL:atomically: will fail.

This is because the convenience methods for reading and writing dictionaries (and arrays) only work if the data in the collection is restricted to property list types. These are:

  • NSString
  • NSNumber
  • NSData
  • NSDate
  • NSArray
  • NSDictionary. And for dictionaries, the keys must be NSStrings.

You can also use mutable subclasses (like NSMutableString) when writing.

If you have anything not on that list, you can't use writeToURL:atomically or any of the similar convenience methods.

The problem is that some valid JSON can't be converted to property lists. Also, some valid property lists can't be converted to JSON (because NSDate won't automatically convert to valid JSON).

If it was me, I'd just write the data to a JSON file. Leave it in its original format. You can convert to/from JSON easily, so leave it that way.

Agnew answered 20/3, 2013 at 19:57 Comment(5)
+1. Yes, you are absolutely Right. There are some <null> values in my JSON Response. So What to do ?Tercel
Like I said, I think the best idea is to leave the data as JSON and write that to a file instead of trying to use a property list. If you must use a property list, you will need to scan the entire dictionary and convert the nulls into something that can be saved in a property list file.Agnew
i want to say more than just "i agree", and so i will support what @TomHarrington is saying by mentioning that i do have an app that turns json into a PropertyList so that it can be written to NSUserDefaults. and to do that, the only solution for the <null> values in the JSON response is to recognize them one by one and not convert them / not write them out.Samirasamisen
@TomHarrington: I want to change the EDITED Values with the Values inside Response... I think that is not possible with what you are suggesting. As If I leave the data as JSON and write it to file then it can't be updated in a way I want.Tercel
@Vin then like I said, you'll need to scan your JSON to find and eliminate anything that's not valid n property lists.Agnew
H
11

If your dictionary contains NSNull, then writeToURL:atomically: will fail.

For dictionaries, the keys must be NSStrings.

The problem is that some valid JSON can't be converted to property lists. Also, some valid property lists can't be converted to JSON.

Don't Forget, If you must use a property list, you will need to scan the entire dictionary and convert the nulls into something that can be saved in a property list file.

Only Solution is that you have to check all the NULL Values and Replace it with @" ".

Happy Coding...

Hillier answered 1/4, 2013 at 10:0 Comment(0)
I
3
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libraryPath = [paths objectAtIndex:0];
NSString *filename = @"FinalResult.plist";
NSString *pathFilename = [libraryPath stringByAppendingPathComponent:filename];

NSDictionary *dictResult = [json objectForKey:@"myKey"];
[dictResult writeToFile:pathFilename atomically:YES];
Insomniac answered 24/3, 2013 at 7:15 Comment(9)
This is not the Issue, My Freind. Have you checked Tom Harrington's Answer ?Tercel
@Vin you have stated that, you are unable to save data to plist, my answer is for that, and "Tom Harrington" has explained what type of objects you can save in plistInsomniac
The Reason why I am unable to save data to plist is not stated in your Answer.Tercel
alright, that because you are creating filepath URL, you simply need filePath to store itInsomniac
if you have to save with URL then use this [dict writeToURL:path atomically:YES];Insomniac
I think you are not getting My Point. There is nothing wrong in my Code. When you have <null> values in your JSON Response, even your code can't do anything.Tercel
yes, got it, for that you need to show your json response ,so one can find the problem, anyway, now you got your answer, go ahead with that, and sorry for misunderstanding, because everybody answered what you are asking for with you snippet, right?Insomniac
My JSON Response has around 50-60 Values. I can't upload it over Here. FYI , The issue is still unsloved :(Tercel
let us continue this discussion in chatInsomniac
B
1

I build my file urls this way:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *path = [paths objectAtIndex:0];
NSString *filename = @"FinalResult.plist";
NSString *pathFilename = [path stringByAppendingPathComponent:filename];

Then see if this writes:

BOOL success = [dictResult writeToFile:pathFilename atomically:YES];
NSLog(@"success? %d", success);

Edit - Funny, I just recently confronted this problem and then forgot all about it. Some JSON parsers will use [NSNull null] as placeholders for nil values. I wrote this (seriously, just about two weeks ago and then spaced on it) to clean up the parse result...

- (NSDictionary *)compact:(NSDictionary *)aDictionary {

    NSDictionary *answer = [NSMutableDictionary dictionary];

    for (NSString *key in [aDictionary allKeys]) {
        id value = [self.dictionary valueForKey:key];
        if (value && value != [NSNull null]) {
            [answer setValue:value forKey:key];
        }
    }
    return [NSDictionary dictionaryWithDictionary:answer];
}

This could be made into a NSDictionary category addition if you wanted.

Batish answered 20/3, 2013 at 15:5 Comment(5)
I got the path but .plist file is not created.Tercel
@Vin can build your own dictionary with just a string key and value, see of that writes? Since you got the dictionary from Jason, I think everyone here is assuming its serializable, but let's start running things out. A simple dictionary writing properly will tell us a lot.Batish
@danh: It's working perfectly with the simple dictionary.The Problem is due to some <null> values in JSON response as told by Tom, I think so.Tercel
@danh: Have you checked "Other Problem" section in my Question ?Tercel
@Vin. I can't explain that (including with the NSNull theory). Just in case, I added the code I wrote recently to clean up a JSON parse. The crash seems indicative of something worse. Can you paste an NSLog(@"%@", dictResult); or does that crash too?Batish
P
-1
  • Check if the return value of the writeToURL:atomically: method returns YES.
  • If it doesn't, check if you have write permissions to that URL.
  • Try it with another URL to find out if its the path or the contents of the dictionary that's causing this error.
Paganism answered 20/3, 2013 at 14:30 Comment(0)
M
-1

Try this, it will work :

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"country.plist"];
[jsonData writeToFile:path atomically:YES];
Milt answered 20/3, 2013 at 15:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.