So I've got json-framework up and running on my project, but need help figuring out how to use it to parse this json string:
[
{
"id":"0",
"name":"name",
"info":"This is info",
"tags":
[
{
"id":"36",
"tag":"test tag"
},
{
"id":"37",
"tag":" tag 2"
}
],
"other":"nil"
},
{
"id":"1",
"name":"name",
"info":"This is info",
"tags":
[
{
"id":"36",
"tag":"test tag"
},
{
"id":"37",
"tag":" tag 2"
}
],
"other":"nil"
}
]
Any help and maybe sample code on how to go about this specific type of json would be great. Somehow I can't get it into a dictionary I can read out of. Thanks so much.
The reason why you can't get this string into a dictionary is because it isn't a dictionary, it's an array of dictionaries
You can get the values into an Objective-C object by storing it in an NSArray:
NSArray *objects = (NSArray*) [jsonString JSONValue];
Then, you can loop over those objects that are in the array:
for(NSDictionary *dict in objects) {
NSString *id = (NSString *) [dict objectForKey:#"id"];
NSString *name = (NSString *) [dict objectForKey:#"name"];
NSArray *tags = (NSArray *) [dict objectForKey: #"tags"];
//loop over tags here...
for(NSDictionary *tag in tags) {
NSString *tag_id = (NSString *) [tag objectForKey:#"id"];
NSString *tag_name = (NSString *) [tag objectForKey:#"tag"];
}
//...
}
Related
I am parsing an itunes rss feed with JSON but I have run into a problem. The following code is running properly for one the movieName output but I still don't get the movieSummary output.
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
allDataDictionary = [NSJSONSerialization JSONObjectWithData:webData options:0 error:nil];
feed = [allDataDictionary objectForKey:#"feed"];
arrayOfEntry = [feed objectForKey:#"entry"];
for (NSDictionary *dictionTitle in arrayOfEntry) {
NSDictionary *title = [dictionTitle objectForKey:#"title"];
NSString *labelTitle = [title objectForKey:#"label"];
[arrayLable addObject:labelTitle];
NSDictionary *summary = [dictionTitle objectForKey:#"summary"];
NSString *labelSummary = [summary objectForKey:#"label"];
[arraySummary addObject:labelSummary];
}
movieName.text = [arrayLable objectAtIndex:0];
movieSummary.text = [arraySummary objectAtIndex:0]; //This is not displaying
}
Here is the link that I am parsing: http://itunes.apple.com/us/rss/topmovies/limit=300/json
I run into this situation a lot. I use something like this. Replace your code
NSString *labelTitle = [title objectForKey:#"label"];
[arrayLable addObject:labelTitle];
with
NSString * labelTitle = [ [ title objectForKey:#"label" ] ifNullThenNil ] ;
[ arrayLabel addObject:labelTitle ? labelTitle : #"" ] ; // you could also use #"<unknown>" or similar instead of #""
where -ifNullThenNil is provided via category:
#implementation NSObject (IfNullThenNil)
-(id)ifNullThenNil { return self ; }
#end
#implementation NSNull (IfNullThenNil)
-(id)ifNullThenNil { return nil ; }
#end
The problem was that when I was adding the strings to the Array that it sometimes contained NULL's thus the following code helped me out
if ([[arrayName objectAtIndex:0] isKindOfClass:[NSNull class]]) {
labelName.text = #"This is NULL";
} else {
[arrayName addObject:labelName];
}
if ([[arraySummary objectAtIndex:0] isKindOfClass:[NSNull class]]) {
labelSummary.text = #"This is NULL";
} else {
[arraySummary addObject:labelSummary];
}
I have this json array which I have outlined below. I want to know how I could get all the strings under the "name" key only and place in a certain array to be sorted alphabetically by name and later split into further arrays in accordance to the first letter in the names. Any guide to carrying this out will be much appreciated, thanks. I am using the json kit via github and also NSJSONserialization.
{
"proj_name": "Ant",
"id":
[
{
"name": "David"
},
{
"name": "Aaron"
}
]
},
{
"proj_name": "Dax",
"id":
[
{
"name": "Adrian"
},
{
"name": "Dan"
}
]
}
Here is sample that selects just names and sort them alphabetically. Replace responseData with your data object.
NSMutableArray *names = [[NSMutableArray alloc] init];
NSError* error;
NSArray* json = [NSJSONSerialization
JSONObjectWithData:responseData
options:kNilOptions
error:&error];
for (NSDictionary *proj in json) {
NSArray *ids = [proj objectForKey: #"id"];
for (NSDictionary *name in ids)
{
[names addObject: [name objectForKey: #"name"];
}
}
NSArray *sortedNames = [names sortedArrayUsingSelector: #selector(localizedCaseInsensitiveCompare:)];
Go to http://json.bloople.net/ in this link you can see the structure of your JSON response.
from the above response i can see the response as follow:
Project name: Dax
id : 0 name : Adrian
1 name : Dan
So you can use the NSjsonserialization class from Apple. No need to use JSON kit.
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"Your URL"]]];
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSLog(#"url=%#",request);
id jsonObject = [NSJSONSerialization JSONObjectWithData:response options:NSJSONReadingAllowFragments error:nil];
if ([jsonObject respondsToSelector:#selector(objectForKey:)])
{
Nsstring *projectname=[jsonObject objectForKey:#"proj_name"];
NSArray *name_array=[jsonObject objectForKey:#"id"];
NSLog(#"projectname=%#",projectname);
NSLog(#"name_array=%#",name_array);
}
Assuming you've successfully parsed the JSON into an NSArray, you can simplify things pretty dramatically:
NSArray *names = [parsedArray valueForKeyPath:#"#distinctUnionOfArrays.id.name"];
The names array should now contain all of the names flattened into a single array. To sort them, you could then do:
NSArray *sortedNames = [names sortedArrayUsingDescriptors:#[[NSSortDescriptor
sortDescriptorWithKey:#"description" ascending:YES]]];
Or all at once:
NSArray *sortedNames = [[parsedArray valueForKeyPath:#"#distinctUnionOfArrays.id.name"]
sortedArrayUsingDescriptors:#[[NSSortDescriptor
sortDescriptorWithKey:#"description"
ascending:YES]]];
The sortedNames array would now contain:
<__NSArrayI 0x713ac20>(
Aaron,
Adrian,
Dan,
David
)
i have this data structure :
{
"artistlist " : [
{
"performer" : "Gate Zero"
},
{
"performer" : "nightech"
},
{
"performer" : "Marko Fuerstenberg"
},
]
}
I read this structure from NSString into NSDictionary with this line of code:
JSON = [NSJSONSerialization JSONObjectWithData:
[[chunks objectAtIndex:1]
dataUsingEncoding:NSUTF8StringEncoding] options:
NSJSONReadingMutableContainers error: &e];
with: [JSON objectForKey:#"artistlist "] i get this structure:
(
{
performer = "Gate Zero";
},
{
performer = nightech;
},
{
performer = "Marko Fuerstenberg";
}
)
Is there any way to go "deeper" ?
how would i parse the resulting Structure ?
I would like to get a list of values or access performer names directly. What if i have several values in a tupel for example performer name, album, year. How would i access those values?
Thank you.
Yes, after you have [JSON objectForKey:#"artistlist "], you get an NSArray of NSDictionaries (slightly confusing!).
NSArray *performersArray = [JSON objectForKey:#"artistlist"];
for (NSDictionary *performerDic in performersArray) {
NSLog(#"%#", [performerDic objectForKey:#"performer"]);
}
This should yield each performer name. Alternatively, you can do for (NSUInteger i = 0; i < [performersArray count]; i++) and access NSDictionary *performersDic = [performersArray objectAtIndex: i]. From there, you can similarly use [performsDic objectForKey:#"performer"]
Like this:
[[[JSON objectForKey:#"artistlist "] objectAtIndex: 1] objectForKey:#"performer"]
It will give you "nightech".
{} corresponds to NSDictionary, [] corresponds to NSArray.
You'll have to use recursion. For example, assuming you have only nested NSDictionaries (easy to modify to work with NSArrays):
- (void) getArtistFromJsonObject:(NSDictionary *)obj {
for (NSString *key in [obj allKeys]) {
id child = [obj objectForKey:key];
if ([child isKindOfClass:[NSString class]]) {
// that's the actual string
// NSLog(#"Found artist: %#", child); // or do whatever needed
} else if ([child isKindOfClass:[NSDictionary class]]) {
[self getArtistFromJsonObject:child];
}
}
}
I'm working with parsing JSON into my app and am running into some issues pulling in just one section of it. For some reason, it seems to be going through my whole JSON feed, logging NULL values except for the one I specify.
Any advice? Thanks for the help!
My Method:
-(void)loadStats {
NSDictionary *totalsfeed = [self downloadTotals];
NSArray *totals = (NSArray *)[totalsfeed valueForKey:#"totals"];
NSLog(#"NEW TOTALS: %#", [totals valueForKey:#"d_monthly_total"]);
}
Console Results:
2011-08-30 11:35:38.096 App Name [9142:16507] NEW TOTALS: (
"<null>",
"<null>",
2,
"<null>",
"<null>",
"<null>"
)
JSON Feed
{
"totals": [
{
"ab_grand_total": "2217"
},
{
"d_grand_total": "1096"
},
{
"d_monthly_total": "2"
},
{
"ab_monthly_total": "13"
},
{
"ab_yearly_total": "746"
},
{
"d_yearly_total": "233"
}
]
}
I'm parsing the JSON here:
// JSON from Server Actions
- (NSString *)stringWithUrl:(NSURL *)url {
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadRevalidatingCacheData
timeoutInterval:30];
// Fetch the JSON response
NSData *urlData;
NSURLResponse *response;
NSError *error;
// Make synchronous request
urlData = [NSURLConnection sendSynchronousRequest:urlRequest
returningResponse:&response
error:&error];
// Construct a String around the Data from the response
return [[NSString alloc] initWithData:urlData encoding:NSUTF8StringEncoding];
}
- (id)objectWithUrl:(NSURL *)url {
SBJsonParser *jsonParser = [SBJsonParser new];
NSString *jsonString = [self stringWithUrl:url];
// Parse the JSON into an Object
return [jsonParser objectWithString:jsonString error:NULL];
}
- (NSDictionary *)downloadTotals {
id totals = [self objectWithUrl:[NSURL URLWithString:#"http://example.com/totals.json"]];
NSDictionary *totalsfeed = (NSDictionary *)totals;
return totalsfeed;
}
totals is an NSArray of NSDictionary objects, so [totals valueForKey:#"d_monthly_total"] does not make sense. Instead, to get d_monthly_total, you should do:
NSDictionary *dMonthlyTotalDictionary = (NSDictionary *)[totals objectAtIndex:2];
NSLog(#"NEW TOTALS: %#", [dMonthlyTotalDictionary objectForKey:"d_monthly_total"]);
To iterate through totals, do:
for(NSDictionary *myDict in totals) {
for(NSString *key in myDict) {
NSLog(#"%#: %#", key, [myDict objectForKey:key]);
}
}
Don't you have the NSDictionary and NSArray the wrong way around for the JSON you show here - wouldn't you expect the NSArray to be the outer container?
If you can control your JSON feed, you should merge these totals into a single has, e.g.:
{"ab_grand_total": "2217",
"ab_grand_total": "2217",
"d_grand_total": "1096"
}
and then load it as an NSDictionary instead of an NSArray.
I have some problem with JSON parsing. When I hit URL, I've got JSON response like this:
//JSON 1
{ "data":
{"array":
["3",
{"array":
[
{"id":"1","message":"Hello","sender":"inot"},
{"id":"2","message":"World","sender":"inot"},
{"id":"3","message":"Hi","sender":"marza"}
]
}
]
},
"message":"MSG0001:Success",
"status":"OK"
}
But if the result of data is just 1, the JSON response is like this:
//JSON 2
{ "data":
{"array":
["3",
{"array":
{"id":"3","message":"Hi","sender":"marza"}
}
]
},
"message":"MSG0001:Success",
"status":"OK"
}
I implement this code to get the id, message and sender value, and work fine on JSON 1, but error on JSON 2. I use JSON-Framework. And the question is how to detect that the JSON response is object ({ }) or array ([ ]) ??
// Parse the string into JSON
NSDictionary *json = [myString JSONValue];
// Get all object
NSArray *items = [json valueForKeyPath:#"data.array"];
NSArray *array1 = [[items objectAtIndex:1] objectForKey:#"array"];
NSEnumerator *enumerator = [array1 objectEnumerator];
NSDictionary* item;
while (item = (NSDictionary*)[enumerator nextObject]) {
NSLog(#"id = %#",[item objectForKey:#"id"]);
NSLog(#"message = %#",[item objectForKey:#"message"]);
NSLog(#"sender = %#",[item objectForKey:#"sender"]);
}
You can use id and check if the object that you get is NSArray or NSDictionary like this:
id item = [json valueForKeyPath:#"data.array"];
if ([item isKindOfClass:[NSArray class]]) {
// item is an array
}
else if ([item isKindOfClass:[NSDictionary class]]) {
// item is a dictionary
}