Access Nested NSDictionary Items - ios

I have this NSDictionary that i received from an api call:
{
items = (
{
accessInfo = {
accessViewStatus = SAMPLE;
country = US;
embeddable = 1;
epub = {
isAvailable = 0;
};
pdf = {
isAvailable = 0;
};
publicDomain = 0;
quoteSharingAllowed = 0;
textToSpeechPermission = ALLOWED;
viewability = PARTIAL;
webReaderLink = "http://books.google.com/books/reader?id=LdB2_WzYpKgC&hl=&printsec=frontcover&output=reader&source=gbs_api";
};
etag = 1xxAlevFUSc;
id = "LdB2_WzYpKgC";
kind = "books#volume";
saleInfo = {
country = US;
isEbook = 0;
saleability = "NOT_FOR_SALE";
};
searchInfo = {
textSnippet = "The saga of their daily exploits won cartoonist Bill Watterson the coveted Reuben Award for "Outstanding Cartoonist of the Year." Something Under the Bed Is Drooling is a jewel.";
};
selfLink = "https://www.googleapis.com/books/v1/volumes/LdB2_WzYpKgC";
volumeInfo = {
authors = (
"Bill Watterson"
);
averageRating = "4.5";
canonicalVolumeLink = "http://books.google.com/books/about/Something_Under_the_Bed_Is_Drooling.html?hl=&id=LdB2_WzYpKgC";
categories = (
Humor
);
contentVersion = "0.0.1.0.preview.1";
description = "\"Be good to yourself: Buy a copy of this Calvin and Hobbes cartoon book. If you don't laugh out loud at every third strip, check your pulse. You may be dead.\" --Phil Musick, Pittsburgh Press Calvin is a rambunctious six-year-old whose manic antics threaten world peace. Hobbes is his stuffed tiger who comes alive when adults aren\"t around. The saga of their daily exploits won cartoonist Bill Watterson the coveted Reuben Award for \"Outstanding Cartoonist of the Year.\" Something Under the Bed Is Drooling is a jewel.";
imageLinks = {
smallThumbnail = "http://bks8.books.google.com/books?id=LdB2_WzYpKgC&printsec=frontcover&img=1&zoom=5&edge=curl&source=gbs_api";
thumbnail = "http://bks8.books.google.com/books?id=LdB2_WzYpKgC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api";
};
industryIdentifiers = (
{
identifier = 0836218256;
type = "ISBN_10";
},
{
identifier = 9780836218251;
type = "ISBN_13";
}
);
infoLink = "http://books.google.com/books?id=LdB2_WzYpKgC&dq=isbn:0836218256&hl=&source=gbs_api";
language = en;
pageCount = 127;
previewLink = "http://books.google.com/books?id=LdB2_WzYpKgC&printsec=frontcover&dq=isbn:0836218256&hl=&cd=1&source=gbs_api";
printType = BOOK;
publishedDate = "1988-01-01";
publisher = "Andrews McMeel Publishing";
ratingsCount = 18;
readingModes = {
image = 1;
text = 0;
};
title = "Something Under the Bed Is Drooling";
};
}
);
kind = "books#volumes";
totalItems = 1;
}
What I want to do is create an object from the items in this dictionary. This method needs to work generically for all books without crashing. Even if they are missing some of the attributes. The attributes I need to extract are:
-authors last name (Need for every author listed if there is more than one)
-authors first name (Need for every author listed if there is more than one)
-title
-description
-smallThumbnail
-thumbnail
-isbn_10 identifier
-category
From these I am going to create a "book" object. i will also create an NSSet of Authors, and each Author has a lastName and firstName
How do I go about doing this?

You should be able to safely use NSDictionary's -valueForKeyPath: to retrieve each value from an item dict:
NSArray *names = [itemDict valueForKeyPath:#"volumeInfo.authors"];
NSString *title = [itemDict valueForKeyPath:#"volumeInfo.title"];
...

Related

How to efficiently extract data from JSON dictionary

I have recently used the following code to extract the ID of a location from a Foursquare API call with:
NSDictionary* foursquareJson = [NSJSONSerialization JSONObjectWithData:secureData options:kNilOptions error:&error];
NSDictionary *venuesDict = foursquareJson[#"response"];
NSArray *venuesArray = venuesDict[#"venues"];
NSDictionary *venuesDict2 = venuesArray[0];
NSArray *categoriesDict = venuesDict2[#"categories"];
NSDictionary *idDict = categoriesDict[0];
NSLog(#"ID is %#",idDict[#"id"]);
with original foursquareJson being:
2015-03-30 17:16:40.700 Voyagic[2833:718563] {
meta = {
code = 200;
};
response = {
venues = (
{
categories = (
{
icon = {
prefix = "https://ss3.4sqi.net/img/categories_v2/building/conventioncenter_";
suffix = ".png";
};
id = 4bf58dd8d48988d1ff931735;
name = "Convention Center";
pluralName = "Convention Centers";
primary = 1;
shortName = "Convention Center";
}
);
contact = {
formattedPhone = "+44 20 7222 5000";
phone = "+442072225000";
};
hereNow = {
count = 0;
groups = (
);
summary = "Nobody here";
};
id = 4b6599d4f964a520f8f52ae3;
location = {
address = "Broad Sanctuary";
cc = GB;
city = London;
country = "United Kingdom";
distance = 2167;
formattedAddress = (
"Broad Sanctuary",
London,
"Greater London",
"SW1P 3EE",
"United Kingdom"
);
lat = "51.49997800145596";
lng = "-0.1289014132864838";
postalCode = "SW1P 3EE";
state = "Greater London";
};
name = "Queen Elizabeth II Conference Centre";
referralId = "v-1427732200";
specials = {
count = 0;
items = (
);
};
stats = {
checkinsCount = 3657;
tipCount = 15;
usersCount = 2407;
};
verified = 0;
}
);
};
}
but there surely must be a better way of accessing the ID which I don't know about (instead of creating 4 dictionaries and 2 array, which seems somewhat excessive :/ ). Any help would be greatly appreciated :)
Ultimately, the data will need to be accessed through the lists of dictionaries and arrays somehow, it just depends on where you want that to happen. You could use or make a parser for the JSON but that will ultimately still need to map the JSON data similarly to what you are doing. A simple and shorter way of accessing the data would be to not create a new variable in every iteration. Although it really is not much different:
NSDictionary *foursquareJson = [NSJSONSerialization JSONObjectWithData:secureData options:kNilOptions error:&error];
NSDictionary *objectId = foursquareJson[#"response"][#"venues"][0][#"categories"][0][#"id"];
NSLog(#"ID is %#",objectId);
Because of the dialogue in the comments of this answer I figured I should probably include a bit more information about your concern with creating "4 dictionaries and 2 arrays". When you use the JSON Serializer to create native objects from the JSON (first line above) you are creating all of the arrays and dictionaries needed to fully represent and store the entire JSON. The difference in code samples between what you originally posted and what I provided is really not a significantly different. If you are concerned with creating too many dictionaries or arrays you should attempt to filter out the JSON prior to deserializing it into native objects.

Extracting an NSDictionary from within another NSDictionary

My application has an NSDictionary containing many other NSDictionary inside it. If I print out this dictionary it reads as follows:
oxip = {
created = "2014-02-10 14:42:59";
lastMsgId = "";
requestTime = "1.6434";
response = {
code = 001;
debug = "";
message = success;
request = getHierarchyByMarketType;
text = "\n";
williamhill = {
class = {
id = 1;
maxRepDate = "2014-02-10";
maxRepTime = "07:31:48";
name = "UK Football";
text = "\n";
type = (
{
id = 2;
lastUpdateDate = "2013-12-26";
lastUpdateTime = "13:32:54";
market = (
{
betTillDate = "2014-02-15";
betTillTime = "15:00:00";
date = "2014-02-15";
id = 140780553;
lastUpdateDate = "2014-02-10";
lastUpdateTime = "14:09:13";
name = "Queen of the South v Dundee - Match Betting";
participant = (
{
handicap = "";
id = 496658381;
lastUpdateDate = "2014-02-10";
lastUpdateTime = "14:09:13";
name = Dundee;
odds = "11/8";
oddsDecimal = "2.38";
text = "\n\n\n\n\n\n";
},
{
handicap = "";
id = 496658380;
lastUpdateDate = "2014-02-10";
lastUpdateTime = "14:09:13";
name = Draw;
odds = "5/2";
oddsDecimal = "3.50";
text = "\n";
},
{
handicap = "";
id = 496658379;
lastUpdateDate = "2014-02-10";
lastUpdateTime = "14:09:13";
name = "Queen of the South";
odds = "11/8";
oddsDecimal = "2.38";
text = "\n";
}
);
text = "\n";
time = "15:00:00";
}
What is the best possible way for my application to reach the NSDictionary with the name of:
name = "Queen of the South v Dundee - Match Betting"
without the need of going through each individual dictionary and finding its object for key?
You can use valueForKeyPath for that. It accepts a path, separated by dots. Example:
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"https://dl.dropboxusercontent.com/u/1365846/21680479.json"]]
options:0
error:nil];
NSLog(#"%#", [dict valueForKeyPath:#"response.williamhill.class.type.market.name"]);
This depends on the representation of dictionary. If the williamhill part is changing, then it does not work, of course.
There is no way to obtain a reference within a map data type (in this case, an NSDictionary) without traversing it. Think of the simplified version of this problem: You have a linked list with N elements and you wish to reach the N'th element. Because this is a linked list, you'll have to go through all other N-1 nodes in order to obtain the last reference.
An NSDictionary is a hash based data type in which keys and values are stored. In the case you describe, you have no reference to the nested object (an NSDictionary itself) so you must also traverse all of the dictionaries containing it.
Hope this helps point you in the right direction.

Parsing Vimeo Json response in ios

I got this json response
{
"generated_in" = "0.0283";
stat = ok;
videos = {
"on_this_page" = 3;
page = 1;
perpage = 50;
total = 3;
video = (
{
"embed_privacy" = anywhere;
id = 73198189;
"is_hd" = 1;
"is_watchlater" = 0;
license = 0;
"modified_date" = "2013-08-27 01:29:16";
owner = 20303618;
privacy = anybody;
title = Untitled;
"upload_date" = "2013-08-27 00:57:36";
},
{
"embed_privacy" = anywhere;
id = 73197989;
"is_hd" = 0;
"is_watchlater" = 0;
license = 0;
"modified_date" = "2013-08-27 01:24:17";
owner = 20303618;
privacy = anybody;
title = sample2;
"upload_date" = "2013-08-27 00:52:40";
},
{
"embed_privacy" = anywhere;
id = 72961770;
"is_hd" = 0;
"is_watchlater" = 0;
license = 0;
"modified_date" = "2013-08-23 05:57:48";
owner = 20303618;
privacy = anybody;
title = sample;
"upload_date" = "2013-08-23 05:25:44";
}
);
};
}
when i am trying to parse it for the video id.
The technique i used is
i converted that json into NSDictionary jsondata and
NSString *videoid = [[[jsondata objectForKey:#"videos"]valueForKey:#"video"]valueForKey:#"id"];
NSLog(#"video string is %#",videoid);
the result is:
(
73198189,
73197989,
72961770
)
but i am not able to access the normal string functions on that string to retrieve the id's.
it is saying an error unrecognized selector was sent.
Is there a better way to parse that string, i tried google but every post says the same approach.
You not getting a string but an array of strings, the JSON response holds mutiple videos. The code you used will retrieve all the id of all the videos.
You can loop thru the found videos like:
NSArray *videoIdArray = [jsondata valueForKeyPath:#"videos.video.id"];
for(NSString *videoId in videoIdArray) {
NSLog(#"video string is %#",videoId);
}

NSMutableArray of dictionaries from JSON feed insert new object for key iOS

I receive and array of dictionaries from a JSON feed and assign it to an NSMutableArray called jsonArray i.e:
jsonArray = [deserializedData objectForKey:#"reports"];
The feed looks like this:
reports = (
{
address = "The street";
email = "alex#blah.co.uk";
"eng_id" = 1;
"eng_name" = "Alex McPherson";
"eng_thumb" = "http://someurl/image/1.png";
form = Test;
id = 59;
lat = "51.1438330";
live = 1;
lng = "0.8693330";
location = "17 Victoria Crescent, Ashford, TN23 7HL";
name = "Alex McPherson";
phone = 01233000000;
rid = "A5C963-C95B-C3D639";
title = "#A5C963-C95B-C3D639, Litter";
tm = "2013-04-28 20:44:20";
type = 5;
"type-text" = "Litter";
},
{
address = "The street";
email = "alex#blah.co.uk";
"eng_id" = 2;
"eng_name" = "Rob Burt";
"eng_thumb" = "http://someurl/image/1.png";
form = Test;
id = 122;
lat = "51.1415000";
live = 1;
lng = "0.8715000";
location = "38 Beaver Road, Ashford, TN23 7RP";
name = Alex;
phone = 01233000000;
rid = "5A5C96-9072-6BAFA9";
title = "#5A5C96-9072-6BAFA9, Litter";
tm = "2013-04-28 20:35:56";
type = 8;
"type-text" = "Litter";
};
what I would like to do is insert a new value for key lets say into this jsonArray: distance = "0.16km" but my brain is just not working tonight....
so the new jsonArray should looks like this with the added key value mentioned above:
reports = (
{
address = "The street";
email = "alex#blah.co.uk";
"eng_id" = 1;
"eng_name" = "Alex McPherson";
"eng_thumb" = "http://someurl/image/1.png";
form = Test;
id = 59;
lat = "51.1438330";
live = 1;
lng = "0.8693330";
distance = "0.16km";
location = "17 Victoria Crescent, Ashford, TN23 7HL";
name = "Alex McPherson";
phone = 01233000000;
rid = "A5C963-C95B-C3D639";
title = "#A5C963-C95B-C3D639, Litter";
tm = "2013-04-28 20:44:20";
type = 5;
"type-text" = "Litter";
},
{
address = "The street";
email = "alex#blah.co.uk";
"eng_id" = 2;
"eng_name" = "Rob Burt";
"eng_thumb" = "http://someurl/image/1.png";
form = Test;
id = 122;
lat = "51.1415000";
live = 1;
lng = "0.8715000";
distance = "2.13km";
location = "38 Beaver Road, Ashford, TN23 7RP";
name = Alex;
phone = 01233000000;
rid = "5A5C96-9072-6BAFA9";
title = "#5A5C96-9072-6BAFA9, Litter";
tm = "2013-04-28 20:35:56";
type = 8;
"type-text" = "Litter";
};
basically I have a calculation that takes the long and lat from the feed and works out how far the poi is from my current location of which then I sort the array by using a sort descriptor based on the distance key that I want to insert above. I have the code for this just stuck on inserting into the existing nsmutablearray above
Read the deserialized JSON array as an NSArray (not NSMutableArray).
Then create a mutable copy of that array using something like:
NSMutableArray *mutableArray = [originalArray mutableCopy];
Then insert items into mutableArray.

How to get all the photos when user uploads 2 or more in Facebook for iOS

{
comments = {
count = 0;
};
"created_time" = "2013-01-23T06:12:43+0000";
from = {
id = 1171029418;
name = "Ilse Anhy";
};
icon = "https://fbstatic-a.akamaihd.net/rsrc.php/v2/yz/r/StEh3RhPvjk.gif";
id = "1171029418_10200426347839190";
link = "https://www.facebook.com/photo.php?fbid=10200426378279951&set=a.3604514069432.2168112.1171029418&type=1&relevant_count=2";
"object_id" = 10200426378279951;
picture = "https://fbcdn-photos-a.akamaihd.net/hphotos-ak-ash4/265145_10200426378279951_1504367216_s.jpg";
privacy = {
value = "";
};
"status_type" = "added_photos";
story = "Ilse Anhy added 2 new photos.";
"story_tags" = {
0 = (
{
id = 1171029418;
length = 9;
name = "Ilse Anhy";
offset = 0;
type = user;
}
);
};
type = photo;
"updated_time" = "2013-01-23T06:12:43+0000";
}
In the "story" object it says "Ilse Anhy added 2 new photos."
In the "picture" object it only gives a reference to a single photo. How would I be able to retrieve the other photo?

Resources