I have a NSJSONSerialization JSONObjectWithData where I pass a NSData object. As a result I get a NSString instead of an NSDictionary. The complete line I have is:
NSDictionary* jsonDec = [NSJSONSerialization JSONObjectWithData:jData options:NSJSONReadingAllowFragments error:&error];
And the return is:
Why don't I get a NSDictionary back? My backend is PHP on the server...
Thanks in advance!
NSDictionary *jsonDec;
NSError* error = nil;
jsonDec = [NSJSONSerialization JSONObjectWithData: jData
options: NSJSONReadingMutableContainers
error: &error];
if (error)
{
NSLog(#"Error: %#",error);
}
Apple doc: NSJSONReadingMutableContainers - Specifies that arrays and dictionaries are created as mutable objects.
I use this when consuming JSON responses (mine usually are arrays of dictionaries). I prefer to use object type id and just use introspection to determine whether it is an NSArray or NSDictionary. BTW - my web requests are either done using AFNetworking (v2) or using the Azure SDK.
id jsonDec = [NSJSONSerialization JSONObjectWithData:jData options:0 error:&error];
Related
I am making this app that gets some data from the url (censored). The problem is that I didn't found a solution to get what the PHP script echo.
A normal returned array from that script looks this:
{"user_data": {"id":"78","image":"https://www.i********p.com/uploads/ideas/fun/2017/03/28/78.jpg","idea":"Join Facebook groups related to your passions or hobbies and meet friends.","owner_ID":"1","owner":"Eduard","owner_photo":"https://www.i********p.com/uploads/members/1/1.png","rating":"4","reviews":"1 review","msg":"success"}}
The question is how can I access each value of this array from "user_data" using Objective-c (without a loop)?
The Objective-c code:
- (void)getJSON {
NSError *error;
NSString *url_string = [NSString stringWithFormat: #"https://www.app.i******o.com/getidea.php?topic=%#", ideasTopic];
NSData *data = [NSData dataWithContentsOfURL: [NSURL URLWithString:url_string]];
NSMutableArray *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
if (error) {
NSLog(#"Something went wrong: %#", error);
} else {
NSLog(#"json: %#", json);
NSLog(#"IMAGE: %#", [[json getObjectAtIndex:0] getObjectForKey:#"image"]);
}}
Objective-C supports literal version to access dictionary. You can directly access values by using keys.
NSString *imageUrl = json[#"user_data"][#"image"];
Your json is a dictionary of dictionaries. json[#"user_data"] returns a dictionary with keys and values. You can access values for this dictionary through respective keys. json[#"user_data"][#"image"] gives you required value for respective key.
Edit:
You need to change your json variable type to NSDictionary too.
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
The JSON text you provided is deserialized into NSDictionary object (you can check it yourself, by looking up what class a json variable has in your example).
So to get what you want (ex. image), you simply write
json["user_data"]["image"]
Ok, I am now starting with iOS development and currently playing with NSData using Obj-C. Recently I'm using the URLSession:dataTask:didReceiveData method to get NSData using HTTP POST request. The server will be responding a JSON object containing a JSON array.
Something interesting is that when the response data is too large the NSLog part will print out: "The data couldn't be read because it isn't in the correct format". Below is the function:
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
NSError *error;
// get data from NSData into NSDict
NSDictionary *searchData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
NSArray *test = [NSKeyedUnarchiver unarchiveObjectWithData:data];
NSMutableDictionary *mdict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
NSLog(#"what: %#", mdict);
NSLog(#"received data length: %#", [NSByteCountFormatter stringFromByteCount:data.length countStyle:NSByteCountFormatterCountStyleFile]);
if (error) {
NSLog(#"json error: %#", [error localizedDescription]);
}
}
Just wondering if anyone knows the potential reason causing this problem ??
[Update]
Well, an alternative to solve this problem might be using NSString for data storage. But would have to parse it by myself. I would prefer using NSDictionary though.
Beginner problem: didReceiveData is called when some of the data has arrived, before the data is complete. Read the documentation of didReceiveData, which explains what you need to do. You are trying to parse incomplete data. That won't work.
And when you are handling JSON data, you should never involve any NSString objects, except possibly to log data.
In my case i was hitting POST Method instead of GET. Solved my problem.
At first point you should check if the response received from the API is a valid JSON, can be check by online validators like jsonlint.com. If this is a vaid json, then you are good to go.
Further more you should evaluate the error object on every step when you get it to see which parsing of data cause this problem like:
NSError *error;
// get data from NSData into NSDict
NSDictionary *searchData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
if (error) {
NSLog(#"json error: %#", [error localizedDescription]);
}
NSArray *test = [NSKeyedUnarchiver unarchiveObjectWithData:data];
NSMutableDictionary *mdict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
NSLog(#"what: %#", mdict);
NSLog(#"received data length: %#", [NSByteCountFormatter stringFromByteCount:data.length countStyle:NSByteCountFormatterCountStyleFile]);
if (error) {
NSLog(#"json error: %#", [error localizedDescription]);
}
Also, as you said that:
The server will be responding a JSON object containing a JSON array.
Are you sure it is returning NS(Mutable)Dictionary ?? Try printing it like this:
id response = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
if (error) {
NSLog(#"json error: %#", [error localizedDescription]);
}
else
{
NSLog(#"json data : %#", response);
}
if the data is kind of josn ,you can
NSDictionary *dict= [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:nil];
or
[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding])
,so that you will be get nsdictionary or nsstring data, if you cannot parse it by yourself ,you can user jsonModel tranlte to model .
It may be a problem with your json data I have experienced the same. You have to serialize your json data like this below written code
NSDictionary *dict= [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:nil];
If you are populating json data from data base u have to use Nsarray.
Hope this will help you .
I know we usually use NSDictionary or NSArray while we do serialization but I wonder are there any advantages if we prefer NSDictionary?
NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
This is not a matter of preference. The JSONObjectWithData: method returns an object of type id.
A Foundation object from the JSON data in data, or nil if an error
occurs.
So it is not that you can choose whether you want an NSArray or NSDictionary. In fact, you should always make a check to make sure that the returned object is of a type you expect.
Your code should look like:
NSError* error;
id JSONObject = [NSJSONSerialization JSONObjectWithData:responseData
options:kNilOptions
error:&error];
if ([JSONObject isKindOfClass:[NSDictionary class]])
{
NSDictionary *JSONDictionary = (NSDictionary *)JSONObject;
// Do your stuff.
}
Otherwise, you are risking a crash when JSON returned from the endpoint you are calling is not a dictionary anymore, but an array or anything that you don't expect.
I'm trying to parse this JSON that looks to me like well written, but NSJSONSerialization doesn't think the same AFAIK since it's returning an NSArray.
This is my code:
NSData* gamesData = [NSData dataWithContentsOfURL:
[NSURL URLWithString:#"http://s42sport.com/polarice/json/games.json"]
];
NSDictionary* json = nil;
if (gamesData) {
json = [NSJSONSerialization
JSONObjectWithData:gamesData
options:kNilOptions
error:nil];
NSLog(#"%d",json.count);
}
The questions are,
What's wrong with the JSON? Why NSSerialization doesn't return me the NSDictionary?
Edit: Yes, I just learned about the [...] vs {...}. Thank You.
Parse your json by this way.
NSURL * url=[NSURL URLWithString:#"http://s42sport.com/polarice/json/games.json"];
NSData * data=[NSData dataWithContentsOfURL:url];
NSError * error;
NSMutableDictionary * json=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&error];
NSLog(#"%#",json);
NSArray * array1=[json valueForKey:#"c"];
NSLog(#"%#",array1);
Try this code. this will surely work for you.
NSDictionnary should be used for Object whereas NSArray is use for JSON array
NSArray* json = nil;
if (gamesData) {
json = [NSJSONSerialization
JSONObjectWithData:gamesData
options:kNilOptions
error:nil];
NSLog(#"%d",json.count);
}
The JSON file you listed is an array (it starts and ends with a square bracket) so Objective-C reflects that with an NSArray root object.
I'm new to JSON and don't understand why this is failing. The JSON is valid according to on-line validation tools, but NSJSONSerilization says this the string is invalid. Why is it invalid?
NSString* JSON = #"{\"Questionnaire\":{\"questionnaireid\":1,\"modifiedDate\":\"2012-12-28 15:27:00\"}}";
if (![NSJSONSerialization isValidJSONObject:JSON]) {
return nil;
}
NSError *jsonParsingError = nil;
NSDictionary* data = [NSJSONSerialization dataWithJSONObject:JSON options:NSJSONReadingMutableContainers error:&jsonParsingError];
why you did serialization when you already created JSON yourself ?
What you should do:
NSData *jsonPayload = [JSON dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *data = [NSJSONSerialization JSONObjectWithData:jsonPayload
options:kNilOptions error:&error];
Because a JSON Object must be of type NSArray or a NSDictionary while you are passing a NSString.
From the docs:
An object that may be converted to JSON must have the following
properties:
The top level object is an NSArray or NSDictionary.
All objects are instances of NSString, NSNumber, NSArray, NSDictionary, or NSNull.
All dictionary keys are instances of NSString.
Numbers are not NaN or infinity.
UPDATE
You probably want to do this:
NSData *jsonData = [JSON dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&err];