isValidJSONObject not working as expected - objective-c

After testing, I can only get [NSJSONSerialization isValidJSONObject:] to return a positive on JSON data that I have already parsed with [NSJSONSerialization JSONObjectWithData:options:error:].
According to the official documentation:
isValidJSONObject returns a Boolean value that indicates whether a given object can be
converted to JSON data.
However, despite the fact that the objects I am attempting to convert from JSON to a NSDictionary convert fine, isValidJSONObject returns NO.
Here is my code:
NSURL * url=[NSURL URLWithString:urlString];
NSData * data=[NSData dataWithContentsOfURL:url];
NSError * error=[[NSError alloc] init];
NSMutableDictionary * dict=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
if([NSJSONSerialization isValidJSONObject:data]){
NSLog(#"data is JSON");
}else{
NSLog(#"data is not JSON");
}
if([NSJSONSerialization isValidJSONObject:dict]){
NSLog(#"dict is JSON");
}else{
NSLog(#"dict is not JSON");
}
NSLog(#"%#",dict);
My log contains the following:
data is not JSON
dict is JSON
and then the output of dict, which at this point is a huge NSMutableDictionary object. No errors are generated when running this code, but isValidJSONObject seems to be returning the wrong value when run on data.
How can I get isValidJSONObject to work as expected?

isValidJSONObject tests if a JSON object (a NSDictionary or NSArray) can be successfully
converted to JSON data.
It is not for testing if an NSData object contains valid JSON data. To test for valid
JSON data you just call
[NSJSONSerialization JSONObjectWithData:data ...]
and check if the return value is nil or not.

Related

Converting a JSON file to NSMutableDictionary in Objective C?

I have a json file that looks like this:
{
"data":
{
"level": [
{
//bunch of stuff
}
]
}
}
Now I want to convert that into a array of levels that I can access. If I take away the {"data: part, then I can use this:
NSData *allLevelsData = [[NSData alloc] initWithContentsOfFile:fileLoc];
NSError *error = nil;
NSMutableDictionary *allLevels = [NSJSONSerialization JSONObjectWithData:allLevelsData options:kNilOptions error:&error];
if(!error){
NSMutableArray *level = allLevels[#"level"];
for (NSMutableDictionary *aLevel in level){
//do stuff with the level...
But I have to have the {"data: as part of the file, and I can't figure out how to get a NSData object out of the existing NSData object. Any ideas?
Don't you need to pull the level NSArray out of the data NSDictionary first?
NSData *allLevelsData = [[NSData alloc] initWithContentsOfFile:fileLoc];
NSError *error = nil;
NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:allLevelsData options:kNilOptions error:&error];
if(!error){
NSArray *levels = dataDictionary[#"data"][#"level"];
for (NSDictionary *aLevel in levels){
//do stuff with the level...
You won't get mutable objects back by default and declaring the variables as mutable doesn't make them so. Take a mutableCopy of the result instead (assuming you really do need mutability).
Why are you trying to prune ahead of time? If you decode the original JSON, you'll be able to extract the level array from the data dict in the decoded dict.
It's not clear what else you're trying to accomplish or why you are going the path you ask about. Note, this doesn't necessarily mean your path is wrong, just that without a clearer indication of what goal you're really trying to accomplish or what you've actually tried (and errored/failed, along with how it failed), you're likely only to get vague/general answers like this.

Issue with parsing JSON data

I am trying to convert a string into a json object and am unsure why this is not working. When I nslog the output I am told that urldata is not valid for json serialization however when looking at the string it looks to me like valid json. I have also tried encoding it to an utf8 however it still won't serialize. Am I missing something here? - Note unnecessary code omitted from post.
Get request
urlData = [NSURLConnection sendSynchronousRequest:urlRequest
returningResponse:&response
error:&error];
NSDictionary *tempDict = [NSDictionary alloc];
Parsing
if ([NSJSONSerialization isValidJSONObject:urlData] ) {
NSLog(#"is valid");
tempDict = [NSJSONSerialization JSONObjectWithData:urlData kniloptions error:&error];
}
NSLog(#"is not valid");
Definition:
isValidJSONObject:
Returns a Boolean value that indicates whether a given object can be converted to JSON data.
As you are already mentioning in your question, isValidJSONObject
returns a Boolean value that indicates whether a given object can be
converted to JSON data
In your case, you don't want to create JSON data, but instead create a dictionary out of JSON data. :
tempDict = [NSJSONSerialization JSONObjectWithData:urlData
options:NSJSONReadingMutableContainers
error:&error];
if (!tempDict) {
NSLog(#"Error parsing JSON: %#", error);
}

How to convert json string to nsdictionary on json parser framework on objective c

I am trying to convert raw json string to NSDictionary. but on NSDictionary i got different order of objects as on json string but i need exactly same order in NSDictionary as on json string. following is code i have used to convert json string
SBJSON *objJson = [[SBJSON alloc] init];
NSError *error = nil;
NSDictionary *dictResults = [objJson objectWithString:jsonString error:&error];
From NSDictionary's class reference:
The order of the keys is not defined.
So, basically you can't do this when using a standard NSDictionary.
However, this may be a good reason for subclassing NSDictionary itself. See this question about the details.
NSDictionary is an associative array and does not preserve order of it's elements. If you know all your keys, then you can create some array, that holds all keys in correct order (you can also pass it with your JSON as an additional parameter). Example:
NSArray* ordered_keys = [NSArray arrayWithObjects: #"key1", #"key2", #"key3", .., nil];
for(NSString* key is ordered_keys) {
NSLog(#"%#", [json_dict valueForKey: key]);
}
//parse out the json data
NSError* error;
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:responseData //1
options:kNilOptions
error:&error];
NSArray* latestLoans = [json objectForKey:#"loans"]; //2
NSLog(#"loans: %#", latestLoans); //3
Source: Follow this link http://www.raywenderlich.com/5492/working-with-json-in-ios-5
Good tutorial but works only on iOS5

NSData writeToFile writes Plist successfully, but then crashes, giving NSInvalidArgumentException

I am converting a JSON file to a plist using the new NSJSONSerialization class and NSPropertyListSerialization class. I manage to convert my JSON to a Plist without errors, but then, at my last step, when I go to write the plist to my desktop, the program crashes, but AFTER the Plist has been generated!
NSData *data = [[NSData alloc] initWithContentsOfURL:path]; \\(NSURL *)path -->goes to my JSON file
NSMutableDictionary *json = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingMutableContainers
error:nil];
//the following removes all key/object pairs where the object is null, because NSPropertyListSerialization with throw an error if there are null values
for (id __strong object in [json objectForKey:#"terms"]) {
if ([object objectForKey:#"image"] == [NSNull null]) {
[object removeObjectForKey:#"image"];
}
}
//the following NSPropertyListSerialization method returns an NSData
id plist = [NSPropertyListSerialization dataFromPropertyList:(id)json
format:NSPropertyListXMLFormat_v1_0
errorDescription:nil];
NSError *writeToFileError;
[plist writeToFile:#"/Users/kalaracey/Desktop/test.plist"
atomically:YES
encoding:NSUTF8StringEncoding
error:&writeToFileError];
Then, at this last line, an NSInvalidArgumentException is thrown, and crashes my program. However, the plist was successfully generated! I can read it, and all is well, except my program crashes.
Could someone please explain why this crashes, and how I could avoid crashing?
The problem seems to be that the variable plist is type id. Cast it to NSData and you should be fine.
NSData *plist = (NSData *) [NSPropertyListSerialization ...];
As you correctly point out in the comment, NSData should use the writeToFile:atomically: method.

How to return a raw string of text/json from aspnet mvc and parse it with the iPhone JSON library

I have a web service that returns a raw string of JSON data (sample below)
{'d':{'success':true,'msg':null,'data':[{'productId':'4b7fcb0f818e4a4abaf5b3c78654b631','id':4283}]}}
... And when I attempt to parse this JSON using the popular JSON library for iPhone development I notice a problem in the following method
- (id)objectWithString:(NSString *)repr {
[self clearErrorTrace];
if (!repr) {
[self addErrorWithCode:EINPUT description:#"Input was 'nil'"];
return nil;
}
depth = 0;
c = [repr UTF8String];
id o;
if (![self scanValue:&o]) {
return nil;
}
// more code ...
}
When I hit the last if statement shown I show c to be a valid char (showing the json values inside as expected) but I notice that after o is defined I return nil inside that last if causing this error from the library
#import "NSString+SBJSON.h"
#import "SBJsonParser.h"
#implementation NSString (NSString_SBJSON)
- (id)JSONValue
{
SBJsonParser *jsonParser = [SBJsonParser new];
id repr = [jsonParser objectWithString:self];
if (!repr)
NSLog(#"-JSONValue failed. Error trace is: %#", [jsonParser errorTrace]);
[jsonParser release];
return repr;
}
#end
Any idea what might be wrong with taking a string of what looks like json and trying to parse it like the below?
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[connection release];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
[responseData release];
NSArray *json = [responseString JSONValue]; //here it all fails
}
Just as a note- this works without error when I query a valid json web service from a large company. My app is aspnet mvc and the return line is simply
return this.Content(jsonStringValue, "text/json");
You should use the built in JSON result object from your action method instead of the Content() method:
return Json(data);
It will automatically serialize your object to be valid JSON.
It would be useful to provide actual error messages/traces.
At any rate, your JSON string is not valid: a string in JSON is quoted within double quotes, not single quotes. The following is valid JSON:
{"d":{"success":true,"msg":null,"data":[{"productId":"4b7fcb0f818e4a4abaf5b3c78654b631","id":4283}]}}
Edit: note that your JSON (top level) data represents an object, not an array. Hence
NSArray *json = [responseString JSONValue];
should be replaced with
NSDictionary *json = [responseString JSONValue];
because SBJSON represents JSON objects as dictionaries.