arrayWithContentsOfFile and arrayWithContentsOfURL nil - ios

When I call [NSArray arrayWithContentsOfFile:], I get nil.
NSURL *fileURL = [NSURL URLWithString:className relativeToURL:[self JSONDataRecordsDirectory]];
return [NSArray arrayWithContentsOfFile:[NSString stringWithFormat:#"%#", [fileURL path]]];
Alternatively, I also get nil when I call:
[NSArray arrayWithContentsOfURL:]
The results of all my files are in JSON here:
https://gist.github.com/neverbendeasy/03d047a6789b0ae14e1f
When I check the fileURLs, the data is there.
What am I missing?

You can't load a JSON file using NSArray arrayWith.... That method can only load a plist file with an array as the root.
If your file is a JSON file you should use:
NSData *jsonData = [NSData dataWithContentsOfURL:fileURL];
NSError *error = nil;
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
if (jsonArray) {
// do something with jsonArray
} else {
NSLog(#"Couldn't load JSON from %#: %#", fileURL, error);
}
This assumes the top level of the JSON file is an array.

Use NSURL's
+ (id)fileURLWithPath:(NSString *)path
or
+ (id)fileURLWithPath:(NSString *)path isDirectory:(BOOL)isDir
instead of
+ (id)URLWithString:(NSString *)URLString
when working with the local filesystem.

Related

JSON Serialization returns null from local file

I'm writing JSON to disk, and that works great. But when I try to read it back, it is nil.
Specifically, this line is nil: NSMutableDictionary *jsonDictFromDocuments = [NSJSONSerialization JSONObjectWithData:[jsonString2 dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:&jsonError];. (I tried NSDictionary *jsonDict2 = [NSJSONSerialization JSONObjectWithData:jsonData2 options:kNilOptions error:&jsonError]; too, but still got nil.)
Every line up until that point logs the correct information from what I can tell.
// Read JSON back from disk
NSString *fileName2 = #"/myJSONFull.json";
NSLog(#"FN: %#", fileName2);
NSURL *documentsFolderURL2 = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
NSLog(#"dFURL2: %#", documentsFolderURL2);
NSString *filePath2 = [documentsFolderURL2.path stringByAppendingString:fileName2];
NSLog(#"FP2: %#", filePath2);
NSString *jsonString2 = [[NSString alloc] initWithContentsOfFile:filePath2 encoding:NSUTF8StringEncoding error:NULL];
NSLog(#"JSONs2: %#", jsonString2);
NSError *jsonError;
NSData *jsonData2 = [jsonString2 dataUsingEncoding:NSASCIIStringEncoding];
NSDictionary *jsonDict2 = [NSJSONSerialization JSONObjectWithData:jsonData2 options:kNilOptions error:&jsonError];
NSLog(#"JDFD2: %#", jsonDict2);
NSMutableDictionary *jsonDictFromDocuments = [NSJSONSerialization JSONObjectWithData:[jsonString2 dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:&jsonError];
NSLog(#"JDFD: %#", jsonDictFromDocuments);
Any ideas?
EDIT:
This is what I have now, but it is still nil
// Read JSON back from disk
NSString *fileName2 = #"/myJSONFull.json";
NSURL *documentsFolderURL2 = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
NSString *filePath2 = [documentsFolderURL2.path stringByAppendingString:fileName2];
NSString *jsonString2 = [[NSString alloc] initWithContentsOfFile:filePath2 encoding:NSUTF8StringEncoding error:NULL];
NSError *jsonError;
NSData *data = [NSData dataWithContentsOfFile:filePath2];
NSMutableDictionary *jsonDictFromDocuments = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonError];
Please try this, it uses the URL related API and logs a possible error in the deserialization.
NSString *fileName2 = #"myJSONFull.json";
NSLog(#"FN: %#", fileName2);
NSURL *documentsFolderURL2 = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
NSLog(#"dFURL2: %#", documentsFolderURL2);
NSURL *fileURL = [documentsFolderURL2 URLByAppendingPathComponent:fileName2];
NSLog(#"FP2: %#", fileURL);
NSData *jsonData = [NSData dataWithContentsOfURL:fileURL];
NSError *jsonError;
NSDictionary *jsonDict2 = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&jsonError];
NSLog(#"JDFD2: %# - error: %#", jsonDict2, jsonError);
Edit:
Since your JSON is PLIST in reality –
the error message JSON text did not start... means This is no JSON –
use the appropriate serialization class:
...
NSLog(#"FP2: %#", fileURL);
NSData *plistData = [NSData dataWithContentsOfURL:fileURL];
NSError *plistError;
NSArray *plistArray = (NSArray *)[NSPropertyListSerialization propertyListWithData:plistData
options:NSPropertyListImmutable
format:nil
error:&plistError];
NSLog(#"JDFD2: %# - error: %#", plistArray, jsonError);

iOS - How to properly read JSON file with umlauts

I am having difficulties converting a JSON file into an NSDictionary without losing umlauts.
{
"België": "5",
"Haïti": "45"
}
This is a short version of the contents of a .json file in my supporting files in Xcode.
I need to convert them to an NSDictionary without losing those umlauts.
NSString *file =[[NSBundle mainBundle] pathForResource:#"countries_and_rates" ofType:#"json"];
NSString *cr = [NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:NULL];
After that, I give cr to this method:
+ (NSDictionary*)jsonFromData:(NSData*)data {
if([self isEmpty:data] || ![data isKindOfClass:[NSData class]])
return nil;
NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if(!str)
return nil;
NSError* error;
id json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
if(error)
NSLog(#"************** Error: jsonFromData: %#/%#", error.localizedDescription, error);
if([json isKindOfClass:[NSDictionary class]])
return json;
else if([json isKindOfClass:[NSArray class]])
return [NSDictionary dictionaryWithObject:json forKey:#"results"];
return #{};
}
If someone could help me and tell me what I am doing wrong.
FYI: tried all kinds of encoding, such as NSISO and NSUTF
Don't mess around with encodings, let the framework figure it out for you:
NSData *data = [NSData dataWithContentsOfFile:filepath];
NSError *error = nil;
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];

Json to iOS Encoding Error

Problem: I can't parse data from a JSON file to a NSArray appropriately. UTF encoding is not working as expected.
My JSON looks something like:
[
{"Name":"Marcos","Address":"1234 Brasil Av. São Paulo - SP","Latitude":"-23.000","Longitude":"-46.70"},{"Name":"Mario","Address":"1000 Washignton Luiz Av. Itú SP","Latitude":"-20.0000","Longitude":"-46.000"}
]
My Objective-C code is:
NSError *error = nil;
NSURL *jsonUrl = [[NSURL alloc]initWithString:
#"http://marcosdegni.com.br/teste/webservice_teste.php"];
NSString *jsonString = [NSString stringWithContentsOfURL:jsonUrl
encoding:NSUTF8StringEncoding error:&error];
NSLog(#"jsonString: %# , Error:%#:" ,jsonString, error); //(1)
if (!error) {
NSError *error2 = nil;
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSArray * jsonArray = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&error2];
NSLog(#"\n\nArray: %#" \nError:$#, jsonArray, error2); //(2)
//(*1*) This log show the content's as they are expected: note the characters ã and ú on the address fields.
//(*2*) The logs from the array and the dictionary show this charters as it's UNIX codes:\U00e and \U00fa respectively.
You can give this a try. The id json you get will be a NSArray, you can use it from there.
NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSArray * array = json;
for (NSDictionary *dict in array) {
NSString *string = [dict objectForKey:#"Address"];
NSLog(#"%#",string);
}
From here, and I get the right result if I obtain the value of the key and log it, instead of logging the NSArray directly.

Using NSArray and NSDictionary to access a JSON object without a root element

Here's an example of my data:
[
{
code: "DRK",
exchange: "BTC",
last_price: "0.01790000",
yesterday_price: "0.01625007",
top_bid: "0.01790000",
top_ask: "0.01833999"
}
]
I'm trying to retrieve the value for last_price by loading the contents of my NSDictionary into an Array.
NSURL *darkURL = [NSURL URLWithString:#"https://api.mintpal.com/v1/market/stats/DRK/BTC"];
NSData *darkData = [NSData dataWithContentsOfURL:darkURL];
NSError *error = nil;
NSDictionary *darkDict = [NSJSONSerialization JSONObjectWithData:darkData options:0 error:&error];
self.darkPosts = [NSMutableArray array];
NSArray *darkPostArray = [darkDict objectForKey:#""];
for (NSDictionary *darkDict in darkPostArray) {...
But my json doesn't have a root element, so what do I do?
Additionally, when using the suggested answer, the output is ("...
- (void)viewDidLoad{
[super viewDidLoad];
NSURL *darkURL = [NSURL URLWithString:#"https://api.mintpal.com/v1/market/stats/DRK/BTC"];
NSData *darkData = [NSData dataWithContentsOfURL:darkURL];
NSError *error = nil;
NSDictionary *darkDict = [NSJSONSerialization JSONObjectWithData:darkData options:0 error:&error];
NSString *lastP = [darkDict valueForKey:#"last_price"];
self.dark_label.text = [NSString stringWithFormat: #"%#", lastP];
}
It looks like you are wanting to iterate over your results. The root element is an array not a dictionary so you can just start iterating
NSError *error = nil;
NSArray *items = [NSJSONSerialization JSONObjectWithData:darkData
options:kNilOptions
error:&error];
if (!items) {
NSLog(#"JSONSerialization error %#", error.localizedDescription);
}
for (NSDictionary *item in items) {
NSLog(#"last_price => %#", item[#"last_price"]);
}
If you literally just want to collect an array of the last_price's then you can so this
NSArray *lastPrices = [items valueForKey:#"last_price"];
Convert the JSON to an NSArray with NSJSONSerialization. Then access the value:
NSData *darkData = [#"[{\"code\":\"DRK\",\"exchange\": \"BTC\",\"last_price\": \"0.01790000\",\"yesterday_price\": \"0.01625007\",\"top_bid\": \"0.01790000\"}, {\"top_ask\": \"0.01833999\"}]" dataUsingEncoding:NSUTF8StringEncoding];
NSArray *array = [NSJSONSerialization JSONObjectWithData:darkData
options:0
error:&error];
NSString *value = array[0][#"last_price"];
NSLog(#"value: %#", value);
NSLog output:
value: 0.01790000
If you are having trouble post the code you have written to get some help.
-- updated for new OP code:
The web service returns a JSON array or dictionaries not a JSON dictionary. First you have to index into the array and then index into the dictionary.
NSURL *darkURL = [NSURL URLWithString:#"https://api.mintpal.com/v1/market/stats/DRK/BTC"];
NSData *darkData = [NSData dataWithContentsOfURL:darkURL];
NSError *error = nil;
NSArray *darkArray = [NSJSONSerialization JSONObjectWithData:darkData options:0 error:&error];
NSDictionary *darkDict = darkArray[0];
NSString *lastP = [darkDict valueForKey:#"last_price"];
NSLog(#"lastP: %#", lastP);
NSLog output:
lastP: 0.01970000
Note that the two lines:
NSDictionary *darkDict = darkArray[0];
NSString *lastP = [darkDict valueForKey:#"last_price"];
can be replaced with the single line using array indexing:
NSString *lastP = darkArray[0][#"last_price"];
Where the "[0]" gets the first array element which is a NSDictionary and the "[#"last_price"]" gets the names item from the dictionary.

Unable to read/parse a local json file

I am trying to parse a json file but I am unable to read/parse the data from the file. I prepared the The json data file by copying the contents from a web service call. I copied the contents and saved it in the projects directory. The path to the file is correct.
NSError *error;
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"Data" ofType:#"js"];
NSLog(#"Path: %#", filePath);
// NSInputStream *fileInputStream = [[NSInputStream alloc] initWithFileAtPath:filePath];
// [fileInputStream open];
// NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithStream:fileInputStream options:0 error:&error];
// NSLog(#"Stream: %#", jsonData);
NSData *fileContents = [[NSData alloc] initWithContentsOfFile:filePath];
NSLog(#"Data: %#", fileContents);
NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:fileContents options:kNilOptions error:&error];
NSLog(#"Dictionary: %#", jsonData);
The "fileContents" prints like "20202020 20202020 20202063 6c756249 64203d20" (may be it is hexadecimal value). Why am I getting the data like this? When I parse same date by calling the web service, it works fine.
I have left some commented code here to let you know that I have tried that portion as well.
Any help is much appreciated!!

Resources