Hi I have the following json that i need to parse, however, I'm struggling to parse the inner array. What I have currently just prints each of the inner arrays but I'd like to print say each title and add the titles to an array. Thank you for any help!
JSON
{"nodes":[{
"node":{
"nid":"1420857",
"title":"Title 1",
"votes":"182",
"popular":"True",
"teaser":"Teaser 1"
}},
{"node":{
"nid":"1186152",
"title":"Title 2",
"votes":"140",
"popular":"True",
"teaser":"Teaser 2"
}},
{"node":{
"nid":"299856",
"title":"Title 3",
"votes":"136",
"popular":"True",
"teaser":"Teaser 3"
}}
]}
Json Parser
NSError *error = nil;
NSData *jsonData = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://www.somefilename.json"]];
if (jsonData) {
id jsonObjects = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
if (error) {
NSLog(#"error is %#", [error localizedDescription]);
return;
}
NSArray *keys = [jsonObjects allKeys];
for (NSString *key in keys) {
NSLog(#"%#", [jsonObjects objectForKey:key]);
}
} else {
// Handle Error
}
Just typecast it:
NSArray *nodes = (NSArray*)[jsonObjects objectForKey:#"nodes"];
for (NSDictionary *node in nodes){
// do stuff...
}
Methods that return id (like -[objectForKey:], and -[objectAtIndex:]) can return any objective-c object. You'll need to know ahead of time what to typecast it into to perform the appropriate operations on it. JSON is converted to the NSObject equivalents:
object -> NSDictionary
array -> NSArray
string -> NSString
number -> NSNumber
boolean -> NSNumber
float -> NSNumber
null -> NSNull
To differentiate between the various NSNumbers, you'll have to call the appropriate type method: -[intValue], -[boolValue], -[floatValue]. Check out the NSNumber docs for more info.
You can use my method for json parsing,
Parse Method:
-(void)jsonDeserialize:(NSString *)key fromDict:(id)content completionHandler:(void (^) (id parsedData, NSDictionary *fromDict))completionHandler{
if (key==nil && content ==nil) {
completionHandler(nil,nil);
}
if ([content isKindOfClass:[NSArray class]]) {
for (NSDictionary *obj in content) {
[self jsonDeserialize:key fromDict:obj completionHandler:completionHandler];
}
}
if ([content isKindOfClass:[NSDictionary class]]) {
id result = [content objectForKey:key];
if ([result isKindOfClass:[NSNull class]] || result == nil) {
NSDictionary *temp = (NSDictionary *)content;
NSArray *keys = [temp allKeys];
for (NSString *ikey in keys) {
[self jsonDeserialize:key fromDict:[content objectForKey:ikey] completionHandler:completionHandler];
}
}else{
completionHandler(result,content);
}
}
}
Method Call:
NSData *content = [NSData dataWithContentsOfFile:[[NSBundle mainBundle]pathForResource:#"Sample" ofType:#"json"]];
NSError *error;
//to get serialized json data...
id dictionary = [NSJSONSerialization JSONObjectWithData:content options:NSJSONReadingMutableContainers error:&error];
//get data for key called GetInfo
[self jsonDeserialize:#"GetInfo" fromDict:dictionary completionHandler:^(id parsedData, NSDictionary *fromDict) {
NSLog(#"%# - %#",parsedData,fromDict);
}];
Related
I have a JSON like below (getting from an URL)-
{
action :getAllJournal;
data :{
journalList :[{
cancelled : F;
"cust_code" : "700-T022";
"journal_amount" : 2216;
"journal_code" : "JV1603/001";
"journal_date" : "2016-03-15 00:00:00";
"journal_id" : 1;
outstanding : 0;
},
{
cancelled : F;
"cust_code" : "700-0380";
"journal_amount" : 120;
"journal_code" : "JV1605/006";
"journal_date" : "2016-05-31 00:00:00";
"journal_id" : 2;
outstanding : 120;
},
{
cancelled : F;
"cust_code" : "700-T280";
"journal_amount" : 57;
"journal_code" : "JV1609/001";
"journal_date" : "2016-09-22 00:00:00";
"journal_id" : 3;
outstanding : 0;
}
];
};
message = "";
"message_code" = "";
result = 1;}
The code below doing is getting the JSON from URL and storing them in NSMutableArray. Until storing them into array, it's working fine but I'm bit confused with the JSON format and don't know how to get result by a key.
__block NSMutableArray *jsonArray = nil;
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
NSString *urlString = [NSString stringWithFormat:#"http://xxxxxxx/api.php?action=getAllJournal"];
NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * response, NSData * data, NSError * connectionError)
{
if (data)
{
id myJSON;
#try {
myJSON = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
}
#catch (NSException *exception) {
}
#finally {
}
jsonArray = (NSMutableArray *)myJSON;
NSString *nsstring = [jsonArray description];
NSLog(#"IN STRING -> %#",nsstring);
NSData *data = [nsstring dataUsingEncoding:NSUTF8StringEncoding];
NSError *jsonError;
NSDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonError];
if(jsonObject !=nil){
if(![[jsonObject objectForKey:#"journalList"] isEqual:#""]){
NSMutableArray *array=[jsonObject objectForKey:#"journalList"];
NSLog(#"array: %lu",(unsigned long)array.count);
int k = 0;
for(int z = 0; z<array.count;z++){
NSString *strfd = [NSString stringWithFormat:#"%d",k];
NSDictionary *dicr = jsonObject[#"journalList"][strfd];
k=k+1;
// NSLog(#"dicr: %#",dicr);
NSLog(#"cust_code - journal_amount : %# - %#",
[NSMutableString stringWithFormat:#"%#",[dicr objectForKey:#"cust_code"]],
[NSMutableString stringWithFormat:#"%#",[dicr objectForKey:#"journal_amount"]]);
}
}
}else{
NSLog(#"Error - %#",jsonError);
}
}
}];
From this, I am able to get the JSON successfully. But it's always giving me this error: Error Domain=NSCocoaErrorDomain Code=3840 "No string key for value in an object around character 6." UserInfo={NSDebugDescription=No string key for value in an object around character 6.} How can I get all values from journalList? I'm new to iOS, that's why not sure what I'm missing.
id myJSON;
#try {
myJSON = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
}
#catch (NSException *exception) {
}
#finally {
}
jsonArray = (NSMutableArray *)myJSON;
NSString *nsstring = [jsonArray description];
NSLog(#"IN STRING -> %#",nsstring);
NSData *data = [nsstring dataUsingEncoding:NSUTF8StringEncoding];
NSError *jsonError;
NSDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonError];
I'd say: NO and NO.
I wouldn't do a #try/#catch on a NSJSONSerialization, because the real issues are on the error parameter (and they won't throw a NSException for most of the cases). Just check if (data) is quite efficient.
Then, let's say it worked, and you have myJSON.
In fact, myJSON is a NSDictionary, not a NSArray, so the cast is useless and doesn't make sense.
Next issue:
Your are using -description (okay, if you want to debug), but you CAN'T use it to reconstruct AGAIN a JSON. It's not a valid JSON, it's the way the compiler "print" an object, it adds ";", etc.
If your print [nsstring dataUsingEncoding:NSUTF8StringEncoding] and data you'll see that they aren't the same.
For a more readable:
NSString *dataJSONStr = [[NSString alloc] initWithData:data encoding: NSUTF8StringEncoding];, it's clearly not the same structure as your nsstring.
Then, you are redoing the JSON serialization? Why ?
So:
NSError *errorJSON = nil;
NSDictionary *myJSON = [NSJSONSerialization JSONObjectWithData:data options:0 error:&errorJSON];
if (errorJSON)
{
NSLog(#"Oops error JSON: %#", errorJSON);
}
NSDictionary *data = myJSON[#"data"];
NSArray *journalList = data[#"journalList"]
for (NSDictionary *aJournalDict in journalList)
{
NSUInteger amount = [aJournalDict[#"journal_amount"] integerValue];
NSString *code = aJournalDict[#"journal_code"];
}
There is a dictionary named "data" you're not fetching, represented by {}.
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonError];
if (!jsonError) {
// Fetch the journalList
NSArray *journalList = json[#"data"][#"journalList"];
// iterate over every entry and output the wanted values
for (NSDictionary *journal in journalList) {
NSLog(#"%# %#", journal[#"cust_code"], journal[#"journal_amount"]);
}
}
json[#"key"] is a short form of [json objectForKey:#"key"] I find easier to read.
That is not a valid JSON. Entries should be separated by comma ,, not semicolon ;
You need to fetch journalList from data.
Try below code:
This is demo code to create array like you:
NSMutableDictionary *jsonObject = [NSMutableDictionary new];
jsonObject[#"action"]= #"";
jsonObject[#"message"]= #"";
jsonObject[#"message_code"]= #"";
jsonObject[#"result"]= #"1";
NSMutableArray *ary1 = [NSMutableArray new];
for(int i=0;i<5;i++)
{
NSMutableDictionary *dd = [NSMutableDictionary new];
dd[#"cancelled"]= #"F";
dd[#"cust_code"]= #"F";
[ary1 addObject:dd];
}
NSMutableDictionary *dicjournal = [NSMutableDictionary new];
[dicjournal setObject:ary1 forKey:#"journalList"];
[jsonObject setObject:dicjournal forKey:#"data"];
This is main Logic:
NSMutableArray *journalList = [NSMutableArray new];
NSMutableDictionary *dic = [jsonObject valueForKey:#"data"];
journalList = [[dic objectForKey:#"journalList"] mutableCopy];
Looks like your JSON is invalid. You can see whether your JSON is correct or not using http://jsonviewer.stack.hu/ and moreover format it. Meanwhile your code is not using "data" key to fetch "journalList" array.
Code : -
NSDictionary *dic = [jsonObject valueForKey:#"data"];
NSMutableArray *arr = [dic objectForKey:#"journalList"];
for (int index=0 ; index < arr.count ; index++){
NSDictionary *obj = [arr objectAtIndex:index];
// Now use object for key from this obj to get particular key
}
Thanks #Larme and #Amset for the help. I was doing wrong the in the NSMutableArray part. The correct version of this code is in the below:
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
NSString *urlString = [NSString stringWithFormat:#"http://xxxxxxx/api.php?action=getAllJournal"];
NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * response, NSData * data, NSError * connectionError)
{
if (data)
{
id myJSON;
#try {
myJSON = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
}
#catch (NSException *exception) {
}
#finally {
}
NSArray *journalList = myJSON[#"data"][#"journalList"];
for (NSDictionary *journal in journalList) {
NSLog(#"%# %#", journal[#"journal_date"], journal[#"journal_amount"]);
}
}
}];
I am trying to loop over a neatest NSDictionary within a NSDictionary.
currently I have this and this returns the first NSDictionary items
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:response
for (NSString *tempObject in json ) {
NSLog(#"Single element: %#", tempObject);
}
The Above works fine
however I wish to read a array layer lower and the blow is failing,
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:response options:kNilOptions error:&error];
for (id tempObject in json ) {
NSLog(#"Object: %#, Key: %#", [json objectForKey:tempObject], tempObject);
}
Thanks Mich
It's always good to check whether the deserialized object contains ARRAY or DICTIONARY within. You can check the type of object before trying to access it. Something like this.
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:response options:kNilOptions error:&error];
for (id jsonObject in json ) {
NSLog(#"Object: %#, Key: %#", [json objectForKey:tempObject], tempObject);
if ([jsonObject isKindOfClass:[NSDictionary class]]){
NSDictionary *deserializedDictionary = jsonObject;
NSLog(#"Deserialized JSON Dictionary = %#",
deserializedDictionary);
}
else if ([jsonObject isKindOfClass:[NSArray class]]){
NSArray *deserializedArray = (NSArray *)jsonObject;
NSLog(#"Deserialized JSON Array = %#", deserializedArray);
}
else {
/* Some other object was returned. We don't know how to
deal with this situation as the deserializer only
returns dictionaries or arrays */
}
}
Hope it helps you!!
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:response options:kNilOptions error:&error];
for (NSString *tempObject in json ) {
NSLog(#"Object: %#, Key: %#", [json objectForKey:tempObject], tempObject);
NSLog(#"Object: %#, Key: %#", [json valueForKey:tempObject], tempObject);
}
//OR by using fast enumeration
[json enumerateKeysAndObjectsUsingBlock:^(id key, id object, BOOL *stop) {
NSLog(#"####Key Value is:%# = %#", key, object);
}];
Hope it helps you....!
I have a for loop going through a dictionary of dictionaries. It works just fine unless there is only one dictionary total.
Here's the gist of my method:
- (NSArray *)objectsFromJSON:(NSString *)jsonString error:(NSError **)error
{
NSParameterAssert(jsonString != nil);
// create JSON object
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSError *localError = nil;
id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&localError];
NSDictionary *dictionaryOfDictionaries = (id)jsonObject;
// if not parsed successfully, error
if(dictionaryOfDictionaries == nil)
{
if(error != NULL)
{
*error = [NSError errorWithDomain:ErrorDomain code:MissingDataError userInfo:nil];
}
return nil;
}
// else create objects out of parsed data
NSMutableArray *objectsArray = [NSMutableArray array];
for(NSDictionary *objectDictionary in dictionaryOfDictionaries)
{
// required properties
Obj *object = [[Obj alloc]
initWithName:objectDictionary[#"name"]
Street:objectDictionary[#"street"]
City:objectDictionary[#"city"]
State:objectDictionary[#"state"]
];
// if error, return
if(object == nil)
{
if(!error)
{
*error = [NSError errorWithDomain:ErrorDomain code:MissingDataError userInfo:nil];
}
return nil;
}
// else add to array of objects created successfully
[objectsArray addObject:object];
}
return [objectsArray copy];
}
As mentioned, this works fine - i.e. all of the objects are created successfully out of the objectDictionary - if there's more than one dictionary in dictionaryOfDictionaries. However, if there is just one dictionary, objectDictionary ends up being type id in the for loop (instead of type Obj), and trying to access its values, such as objectDictionary[#"name"] results in an error.
How do I most efficiently write this so the case of having one dictionary is handled?
Here's the issue. When you have more than one dictionary, you actually get an array of dictionaries. In other words, jsonObject is really an NSArray containing each of the dictionaries.
When there is just one dictionary, jsonObject is just that one dictionary.
Change your code like this:
id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&localError];
NSArray *arrayOfDictionaries = nil;
if (jsonObject == nil) {
// handle error
} else if ([jsonObject isKindOfClass:[NSArray class]]) {
arrayOfDictionaries = jsonObject;
} else {
arrayOfDictionaries = #[ jsonObject ];
}
Then change the for loop to:
for(NSDictionary *objectDictionary in arrayOfDictionaries)
Create Array from json response that would be dictionaries
NSMutableArray *array = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
if (error)
NSLog(#"JSONObjectWithData error: %#", error);
for (NSMutableDictionary *dictionary in array)
{
//Do what you want to do
}
I am getting a json array from the server. The jsonOutput object shows 2 objects correctly. But am unable to display or extract the data. Could some one help me out. I tried
the following way :
for (id key in jsonOutput) {
NSLog(#"key: %#, value: %#", key, [jsonOutput objectForKey:key]);
}
declaration :
NSDictionary *jsonOutput;
actualmethods :
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
data=[[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)theData
{
[data appendData:theData];
// if ([connection isEquals:connect1]){
// this is request urlConnectionRecsender
// }
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
jsonOutput= [NSJSONSerialization JSONObjectWithData:data options:nil error:nil];
for (id key in jsonOutput) {
NSLog(#"key: %#, value: %#", key, [jsonOutput objectForKey:key]);
}
}
Try this
NSError *error;
jsonOutput= [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
if(error)
NSLog(#"%#",error.description);
If you don't know what is response type, then it is always a good practice to check respone type first
id responseObj = [NSJSONSerialization
JSONObjectWithData:data
options:kNilOptions
error:&error];
if ([responseObj isKindOfClass:[NSArray class]]) {
//Your response is a array
}
else if([responseObj isKindOfClass:[NSDictionary class]]) {
//Your response is a dictionary
}
Your array contains NSDictionary
{ cropName = corn; cropOrderId = 1; cropPrice = 100; "farmer_id" = 1; orderStatus = pending; quantity = 5; }
use this code to get value
for(NSDictionary*dict in jsonObject) {
NSArray *allKeysarr = [dic allKeys];
for(NSString *key in allKeysarr) {
NSLog(#"%#",[dic valueForKey:key]);
}
}
first use error handling:
NSError *error;
jsonOutput= [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
if (error) NSLog(#"error: %#",error.description);
then access values with:
NSString *value1 = [jsonOutput objectForKey:#"YOUR_KEY1"];
NSData *xmlData = [NSData dataWithContentsOfFile:xmlPath];
NSError *jsonError = nil;
id jsonObject = [NSJSONSerialization JSONObjectWithData:xmlData options:kNilOptions error:&jsonError];
if ([jsonObject isKindOfClass:[NSArray class]]) {
NSLog(#"its an array!");
NSArray *jsonArray = (NSArray *)jsonObject;
NSLog(#"jsonArray - %#",jsonArray);
}
else {
NSLog(#"its probably a dictionary");
NSDictionary *jsonDictionary = (NSDictionary *)jsonObject;
NSLog(#"jsonDictionary - %#",jsonDictionary);
}
Try this once
I have some NSData coming back from my server that is of type Json. I would like to know how to access the values present in the json and put them into there own NSString objects.
This is what the structure of the JsonArray looks like
This is the code I am using, however my for loop only ever shows "result" and nothing else.
NSError *error = nil;
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:csvData options: NSJSONReadingMutableContainers error: &error];
NSLog(#"%#", jsonArray);
if (!jsonArray) {
NSLog(#"Error parsing JSON: %#", error);
} else {
for(NSDictionary *item in jsonArray) {
NSLog(#"Item: %#", item);
}
}
You can access it like that:
for (NSDictionary *dict in jsonArray)
{
NSLog(#"Data: %#", dict[#"result"]);
}
You have dictionary in your array so you have to enumerate is and access it by key (result, etc.).
NSDictionary *resultDictionary = [jsonArray objectAtIndex: 0];
NSArray *resultArray = [resultDictionary objectForKey:#"result"];
for (NSString *item in resultArray)
{
NSLog (#"item: %#",item);
}
You should add some (non)sense checking.
u can access the json array like this,
for(NSDictionary *Mydictionary in MyJsonArray) {
Nsstring *DataOne = [Mydictionary objectforkey#"Mykey"];
}
For Cheking the json node u can put the json in this site and all the node will appear properly
http://json.parser.online.fr/