Nested NSDictionary from JSON in Xcode - ios

Hi I been having huge issues grabbing some data out of this for me quite complex JSON structure.
The problem is that the JSON structure contains some nesting that i can't find out how to handle.
Example of the JSON i get from the database:
{
"hits": {
"totalHits": 3202,
"hits": [{
"id": "70132eb7-2834-458c-900a-da951c95a506",
"versions": [{
"id": 7,
"properties": {
"Status": [
"usable"
],
"created": [
"2015-10-27T14:31:13Z"
],
"Text": [
"Snabbtåg, Järnväg, Höghastighetsjärnväg, "
],
"ConceptDefinitionLong": [
"Enligt Trafikverket saknas en helt entydig och vedertagen definition av höghastigheteståg."
],
"contenttype": [
"Concept"
],
"ConceptProposalUser": [
"[object Object]"
],
"ConceptType": [
"object"
],
"Name": [
"Höghastighetståg"
],
"ConceptNote": null,
"ConceptSeeAlso": null,
"Note": null,
"ConceptName": [
"Höghastighetståg"
],
"updated": [
"2016-02-01T11:37:30Z"
],
"ConceptDefinitionShort": [
"Snabbtåg, Järnväg, Höghastighetsjärnväg, Kollektivtrafik"
],
"ConceptStatus": [
"usable"
]
}
}],
"noVersions": 1
}, {
"id": "4224ccfb-1f0a-9491-727f-f6ab0fc2c951",
"versions": [{
"id": 2,
"properties": {
"Status": [
"usable"
],
"created": [
"2016-01-25T12:03:33Z"
],
"Text": [
"Rosenlundsbadet öppnade 1968 och äventyrsbadet 1991."
],
"ConceptDefinitionLong": [
"Rosenlundsbadet är en badanläggning i Jönköping. "
],
"contenttype": [
"Concept"
],
"ConceptProposalUser": null,
"ConceptType": [
"organisation"
],
"Name": [
"Rosenlundsbadet"
],
"ConceptNote": null,
"ConceptSeeAlso": null,
"Note": null,
"ConceptName": [
"Rosenlundsbadet"
],
"updated": [
"2016-01-25T12:03:38Z"
],
"ConceptDefinitionShort": [
"Simning, Simhopp, Äventyrsbad"
],
"ConceptStatus": [
"usable"
]
}
}],
"noVersions": 1
}
...
My job is to get all the "Name"s from all posts where the "Status" is set to "usable". And store them in my app. But I'm having a hard time getting that info . Im new to JSON and can't handle the structure. This is what i got so far after hours of googling:
NSData *allCoursesData = [[NSData alloc] initWithContentsOfURL:
[NSURL URLWithString:#"http://www.pumba.se/example.json"]];
NSError *error;
NSMutableDictionary *JSONdictionary = [NSJSONSerialization
JSONObjectWithData:allCoursesData
options:kNilOptions
error:&error];
if( error )
{
NSLog(#"%#", [error localizedDescription]);
}
else {
NSArray* entries = [JSONdictionary valueForKeyPath:#"hits.hits"];
NSDictionary *firstItem = [entries objectAtIndex:0];
NSString *id1 = [firstItem objectForKey:#"id"];
NSLog(#"ID: ");
NSLog(id1);
}}
From that code I'm able to get the ID from the first item. But I don't seem to be able to fetch the "name" or check if they are "usable". Have been working with this and trying to solve this for hours but this is above my leauge. I guess the reason to why I can't solve it is cause the data is nested in hits.hits etc. Yet I have to solve this to be able to finish my app. I would be very grateful for some help.
Here is a longer version of the JSON database. The full version contains over 3000 items:
http://jsonviewer.stack.hu/#http://www.pumba.se/example.json

You can use the following code:
NSData *allCoursesData = [[NSData alloc] initWithContentsOfURL:
[NSURL URLWithString:#"http://www.pumba.se/example.json"]];
NSError *error;
NSMutableDictionary *JSONdictionary = [NSJSONSerialization
JSONObjectWithData:allCoursesData
options:kNilOptions
error:&error];
if( error )
{
NSLog(#"%#", [error localizedDescription]);
}
else {
NSMutableArray *allNames = [NSMutableArray array];
NSArray* entries = [JSONdictionary valueForKeyPath:#"hits.hits"];
for (NSDictionary *hit in entries) {
NSArray *versions = hit[#"versions"];
for (NSDictionary *version in versions) {
NSDictionary *properties = version[#"properties"];
NSString *status = [properties[#"Status"] firstObject];
NSString *name = [properties[#"Name"] firstObject];
if ([status isEqualToString:#"usable"]) {
[allNames addObject:name];
}
}
}
NSLog(#"All names: %#", allNames);
}}

Related

IOS JSON Parsing Containing Multiple Arrays

I have a JSON array with multiple object and I don't know how do I grab the "url" tag as an NSArray or a NSDictionary and show that image url in CollectionView. I can't change the JSON data format.How should I do this?
Here is what the JSON response looks like:
{
"error": false,
"data": [
{
"albumid": 2,
"albumtitle": "Album 2",
"images": [
{
"image": "Img2.jpeg",
"imageid": 11
},
{
"image": "vr4.jpg",
"imageid": 4
},
{
"image": "3purple b-ball.jpg",
"imageid": 3
}
]
},
{
"albumid": 3,
"albumtitle": "Album 3",
"images": [
{
"image": "vr2.jpg",
"imageid": 6
},
{
"image": "vr1.jpg",
"imageid": 5
}
]
},
{
"albumid": 4,
"albumtitle": "Album 4",
"images": [
{
"image": "vr1.jpg",
"imageid": 8
}
]
},
{
"albumid": 12,
"albumtitle": "My Album",
"images": [
{
"image": "img3.jpeg",
"imageid": 64
},
{
"image": "img4.jpeg",
"imageid": 63
},
{
"image": "img5.jpeg",
"imageid": 62
}
]
},
{
"albumid": 13,
"albumtitle": "Demo Album",
"images": [
{
"image": "img6.jpeg",
"imageid": 67
},
{
"image": "img7.jpeg",
"imageid": 66
},
{
"image": "img11.jpeg",
"imageid": 65
}
]
}
]
}
Try something like this (data is the NSData object you get from your webserver):
NSError *jsonError = nil;
NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jsonError];
if(!jsonError){
NSArray *dataArray = [jsonData objectForKey:#"data"];
NSDictionary *albumDict = [dataArray objectAtIndex:0];
NSArray *imagesArray = [albumDict objectForKey:#"images"];
NSDictionary *imageDict = [imagesArray objectAtIndex:0];
NSString *imageURL = [imageDict objectForKey: #"image"];
}
Of course, you have to use loops for the array elements, this example is only with element 0. Some more checks if a field exists etc. would be good.
You can create a model to hold the image id and url. You add an array of these image objects in the main model (Album). In Swift, your models might look like this
class Album {
var albumId = ""
var albumTitle = ""
var albumImages = [AlbumImage]()
}
class AlbumImage {
var imageId = ""
var imageUrl = ""
}
Hope this helps!
Use this code after downloaded the json file.
NSDictionary *rootDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
NSArray *rootArray = rootDict[#"data"];
NSDictionary *subDict;
NSArray *subArray;
NSDictionary *tempDict;
for (int i=0; i<rootArray.count; i++) {
subDict = rootArray[i];
subArray = subDict[#"images"];
for (int j=0; j<subArray.count; j++) {
tempDict = subArray[j];
NSLog(#"%#",tempDict[#"image"]);
}
}
in JSONObjectSerialization data was NSData object where the json file downloaded.

RestKit how to map an array inside an array

Here's the response:
{
"status": true,
"statuscode": 200,
"result": [
{
"name": "ABC",
"date": "2015-01-30",
"documents": [
{
"id": 1,
"name": "doc1",
"status": "complete",
},
{
"id": 2,
"name": "doc2",
"status": "complete",
},
{
"id": 3,
"name": "doc3",
"status": "complete",
}
],
"message": "Hello World",
"status": 3
}
]
}
I want to map and get only all the "document" inside an array keyed "result" and I don't need anything with other objects / mappings. I just need the documents. How can that be done / declared in the response descriptors to automatically match all these documents to my managed object?
Try This :-
NSDictionary *dic=#{
#"status": #true,
#"statuscode":# 200,
#"result": #[
#{
#"name": #"ABC",
#"date": #"2015-01-30",
#"documents": #[
#{
#"id":# 1,
#"name": #"doc1",
#"status": #"complete",
},
#{
#"id":# 2,
#"name": #"doc2",
#"status":# "complete",
},
#{
#"id":# 3,
#"name": #"doc3",
#"status": #"complete",
}
],
#"message": #"Hello World",
#"status":# 3
}
]
};
I am storing your response in NSDictionary and get it by -
[[[dic objectForKey:#"result"] objectAtIndex:0] objectForKey:#"documents"]
change your indexNumber as require !
NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error]; //From Server you will get response data in form of NSData , so the 'responseData' is a type of NSData
NSArray *appDetais = [jsonData objectForKey:#"result"];
NSDictionary *resultJsonData = [appDetais objectAtIndex:0];
NSArray *documentDetailsArray = [jsonData resultJsonData:#"documents"];
for(int i=0;i<[documentDetailsArray count];i++){
NSDictionary *singleDocumentDetail = [documentDetailsArray objectAtIndex:0];
NSLog(#"%#",[singleDocumentDetail objectForKey:#"id"]);
}
You may try this.. :)

Pulling Data from an NSDictionary

So I have an NSDictionary that has a variety of data within it. When printed to the log, it prints like this:
[{"user_id":3016817,"grade":"A","percent":"93","grading_periods":[{"assignments":[{"points":100.0,"grade":"A","score":95.0,"percent":"93","comment":null,"id":3268180},{"points":100.0,"grade":"A","score":90.0,"percent":"93","comment":null,"id":3268181}],"grade":"A","percent":"93","name":"Default"}]},{"user_id":3016818,"grade":"A","percent":"94","grading_periods":[{"assignments":[{"points":100.0,"grade":"A","score":92.0,"percent":"94","comment":null,"id":3268180},{"points":100.0,"grade":"A","score":95.0,"percent":"94","comment":null,"id":3268181}],"grade":"A","percent":"94","name":"Default"}]}]
If I use a formatter online, its a lot more readable and looks something like this:
[
{
"user_id": 3016817,
"grade": "A",
"percent": "93",
"grading_periods": [
{
"assignments": [
{
"points": 100,
"grade": "A",
"score": 95,
"percent": "93",
"comment": null,
"id": 3268180
},
{
"points": 100,
"grade": "A",
"score": 90,
"percent": "93",
"comment": null,
"id": 3268181
}
],
"grade": "A",
"percent": "93",
"name": "Default"
}
]
},
{
"user_id": 3016818,
"grade": "A",
"percent": "94",
"grading_periods": [
{
"assignments": [
{
"points": 100,
"grade": "A",
"score": 92,
"percent": "94",
"comment": null,
"id": 3268180
},
{
"points": 100,
"grade": "A",
"score": 95,
"percent": "94",
"comment": null,
"id": 3268181
}
],
"grade": "A",
"percent": "94",
"name": "Default"
}
]
}
]
My question would be how would I access the value of grade or score for a specific user_id using this dictionary?
Your string represents a NSArray, not a NSDictionary. And it's a JSON string, so you can parse it using NSJSONSerialization:
NSString *jsonString = #"..." // your string here
// Create array from json string
NSArray *jsonArray = [NSJSONSerialization
JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding]
options:NSJSONReadingMutableContainers
error:Nil];
// Loop to find your user_id
// Because each child of this array is a dictionary
for (NSDictionary *dic in jsonArray) {
if ([dic[#"user_id"] isEqual:#3016817]) { // user_id field is number
// Access what you want
NSString *grade = dic[#"grade"];
// For "score" you must go deeper
// Just remember, [] is array and {} is dictionary
}
}
A simple way to do this would be
for (NSDictionary* d in theArray) {
if ([d[#"user_id"] isEqualToString: u]) {
// do something
}
}
And matt is right, it is an array of dictionaries, no matter what type you declared to be.
You can use below class method of NSJsonSerialization class to create NSArray which will contain all the dictionaries.
+ (id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error;
Once you get the array of dictionaries from JSON, you can do following:
NSArray *filteredjsonArr = [jsonArr filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"user_id == %#", #"3016818"]];
NSDictionary *dict = [filtered firstObject];
if (dict != nil) {
NSString *grade = [dict objectForKey:#"grade"];
NSArray *gradingPeriods = [dict objectForKey:#"grading_periods"];
}
To access score and grade for specific assignments, you'll need to drill down further into gradingPeriods array.

Parsing a response from JSON , ios?

I have the below parameter in my json.
{
"msg": "success",
"data": [
{
"FNAME": "test",
"LNAME": null,
"STATUS": null,
"MOBILE1": "1234567890",
"show_email": "1",
"Info": [
{
"id": "73307",
"NAME": "demo",
"CONTACT": "",
"WORKING_HOUR1": "[\"09:00 AM\",\"09:15 AM\",\"09:30 AM\",\"09:45 AM\",\"10:00 AM\"]",
"WORKING_HOUR7": "",
"DAY": "[\"Monday\",\"Wednesday\"]"
}
]
}
]
}
I am not able to understand how do I get values from it.
If I parse this I get the error
NSError *myError = nil;
NSDictionary *res = [NSJSONSerialization JSONObjectWithData:self.responseData options:NSJSONReadingMutableLeaves error:&myError];
NSArray *results = [res objectForKey:#"data"];
NSArray *Info=[results[0] objectForKey:#"Info"];
NSArray *day=clinicInfo[1][#"DAY"];
NSLog(#"%#", day[0]);
Error:
'NSInvalidArgumentException', reason: '-[__NSCFString objectAtIndexedSubscript:
EDIT:
From your JSON you want:
NSArray *days = json[#"data"][0][#"Info"][0][#"DAY"]
Also while your JSON is valid, the days and working hours are not in an array - they are a string.
You need something like this.
{
"msg": "success",
"data": [
{
"FNAME": "test",
"LNAME": null,
"STATUS": null,
"MOBILE1": "1234567890",
"show_email": "1",
"Info": [
{
"id": "73307",
"NAME": "demo",
"CONTACT": "",
"WORKING_HOUR1": [
"09:00 AM",
"09:15 AM",
"09:30 AM",
"09:45 AM",
"10:00 AM"
],
"WORKING_HOUR7": "",
"DAY": [
"Monday",
"Wednesday"
]
}
]
}
]
}
Firstly you are not using valid JSON.
{
"DAY": [
"Monday",
"Wednesday"
]
}
You can use NSJSONSerialization to parse the JSON file, from which you should get a NSDictionary.
In that dictionary there should be a NSArray for the key "DAY", which contains 2 objects both strings, "Tuesday" and "Thursday".
eg. Where data is your JSON file
NSError *jsonError = nil;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jsonError];
if(!jsonError) NSArray *days = json[#"DAY"];
else NSLog(#"Error serialising JSON");

XCode, String encoding, cyrillic letters

I have an issue with my iPhone application or rather Xcode.
I am currently trying to convert a string that i get from Google Translate to a string format that supports cyrillic letters. i tried many String Encodings so far, but none of them seem to work properly.
Here is my code so far:
NSString *word = #"hello";
NSString *urlPath = [NSString stringWithFormat:#"/translate_a/t?client=t&text=%#&langpair=en|ru",word];
NSURL *url = [[NSURL alloc] initWithScheme:#"http" host:#"translate.google.com" path:urlPath];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
[request setHTTPMethod:#"GET"];
NSURLResponse *response;
NSError *error;
NSData *data;
data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *result = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSLog(#"%#", result);
And this is the result on the console:
[
[
[
"ÐÒÉ×ÅÔ",
"hello",
"privet",
""
]
],
[
[
"verb",
[
"ÚÄÏÒÏ×ÁÔØÓÑ",
"Ú×ÁÔØ",
"ÏËÌÉËÁÔØ"
],
[
[
"ÚÄÏÒÏ×ÁÔØÓÑ",
[
"greet",
"hello",
"salute",
"hullo",
"hallo",
"halloa"
],
,
0.0050860695
],
[
"Ú×ÁÔØ",
[
"call",
"invite",
"shout",
"hail",
"hallo",
"hello"
],
,
2.7109536e-05
],
[
"ÏËÌÉËÁÔØ",
[
"hail",
"holler",
"call",
"challenge",
"speak",
"hello"
],
,
2.7109536e-05
]
],
"hello",
2
],
[
"noun",
[
"ÐÒÉ×ÅÔÓÔ×ÉÅ",
"ÐÒÉ×ÅÔÓÔ×ÅÎÎÙÊ ×ÏÚÇÌÁÓ",
"×ÏÚÇÌÁÓ ÕÄÉ×ÌÅÎÉÑ"
],
[
[
"ÐÒÉ×ÅÔÓÔ×ÉÅ",
[
"greeting",
"welcome",
"salute",
"hail",
"salutation",
"hello"
],
,
0.0014801305
],
[
"ÐÒÉ×ÅÔÓÔ×ÅÎÎÙÊ ×ÏÚÇÌÁÓ",
[
"hallo",
"halloa",
"viva",
"hello"
],
,
2.7536449e-05
],
[
"×ÏÚÇÌÁÓ ÕÄÉ×ÌÅÎÉÑ",
[
"hallo",
"halloa",
"hello"
],
,
2.7109536e-05
]
],
"hello",
1
]
],
"en",
,
[
[
"ÐÒÉ×ÅÔ",
[
1
],
true,
false,
1000,
0,
1,
0
]
],
[
[
"hello",
1,
[
[
"ÐÒÉ×ÅÔ",
1000,
true,
false
],
[
"úÄÒÁ×ÓÔ×ÕÊÔÅ",
0,
true,
false
],
[
"Hello",
0,
true,
false
],
[
"úÄÒÁ×ÓÔ×ÕÊ",
0,
true,
false
],
[
"ÈÅÌÌÏ",
0,
true,
false
]
],
[
[
0,
5
]
],
"hello"
]
],
,
[
,
"Hello!",
[
10
],
,
true
],
[
],
2
]
So i hope you get my problem. I want the string to be "привет" and not "ÐÒÉ×ÅÔ".
When i tried to encode the data to other formats i usually get a "(null)" result to my string, like for NSUTF8StringEncoding for example.
"translate.google.com" returns UTF-8 with the following parameters:
NSString *urlPath = [NSString stringWithFormat:#"/translate_a/t?client=t&text=%#&langpair=en|ru&ie=UTF-8&oe=UTF-8",word];
Then
NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
should work.
Call this method on the data you're getting instead of initWithData:encoding::
- (NSString*)decodeKOI8R:(NSData*)dataToDecode {
CFStringRef aCFString = CFStringCreateWithCString(NULL, [dataToDecode bytes], kCFStringEncodingKOI8_R);
NSString *decodedString = (__bridge NSString*)aCFString;
return decodedString;
}

Resources