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 Tableview. I can't change the JSON data format.How should I do this?
Here is what the JSON response looks like:
{
"meta": {
"total_count": 10
},
"pages": [
{
"id": 7,
"meta": {
"type": "dashboard.NewsEvents",
"detail_url": "http://suno.to/api/v1/pages/7/"
},
"title": "NoEvent",
"created_at": "2016-03-06T10:42:19.646000Z",
"cover_url": [
[
{
"url": "/media/images/Maha_Shivratri2.original.jpg",
"title": "Maha Shivratri2.jpg"
},
{
"url": "/media/images/Maha_Shivratri1.original.jpg",
"title": "Maha Shivratri1.jpg"
}
],
[
{
"url": "/media/images/Celebrations.original.jpg",
"title": "Celebrations.jpg"
},
{
"url": "/media/images/Crew.original.jpg",
"title": "Crew.jpg"
},
{
"url": "/media/images/World_record.original.jpg",
"title": "World record.jpg"
},
{
"url": "/media/images/AI_pilots.original.jpg",
"title": "AI pilots.jpg"
}
],
[
{
"url": "/media/images/CbVv-VbWEAAmwv_.original.jpg",
"title": "DAL SWARAJ YATRA"
},
{
"url": "/media/images/CbVv_-TWwAE7RjM.original.jpg",
"title": "DAL SWARAJ YATRA"
},
{
"url": "/media/images/CbVv_SmXIAALQP8.original.jpg",
"title": "DAL SWARAJ YATRA"
},
{
"url": "/media/images/CahEc--UkAArc_z.original.jpg",
"title": "DAL SWARAJ YATRA"
}
]
]
},
{
"id": 2530,
"meta": {
"type": "dashboard.NewsEvents",
"detail_url": "http://suno.to/api/v1/pages/2530/"
},
"title": "World Culture Festival",
"created_at": "2016-03-12T06:59:21.023000Z",
"cover_url": [
[
{
"url": "/media/images/Security.original.jpg",
"title": "Security check"
}
],
[
{
"url": "/media/images/Elephant_statues.original.jpg",
"title": "Elephant"
}
],
[
{
"url": "/media/images/6.original.jpg",
"title": "Stage"
},
{
"url": "/media/images/4.original.jpg",
"title": "Stage"
}
]
]
},
{
"id": 2675,
"meta": {
"type": "dashboard.NewsEvents",
"detail_url": "http://suno.to/api/v1/pages/2675/"
},
"title": "Holi in Barsana",
"created_at": "2016-03-17T12:35:09.308000Z",
"cover_url": [
[
{
"url": "/media/images/Brajwasi_playing_holi_.original.jpg",
"title": "Holi in Barsana"
},
{
"url": "/media/images/dancing_.original.jpg",
"title": "Holi in Barsana"
},
{
"url": "/media/images/holi.._.original.jpg",
"title": "Holi in Barsana"
},
{
"url": "/media/images/holi..._.original.jpg",
"title": "Holi in Barsana"
}
],
[
{
"url": "/media/images/Lathmar_holi_19_n54f7LJ.original.jpg",
"title": "Lathmar Holi in Barsana"
}
],
[
{
"url": "/media/images/Lathmar_holi_17.original.jpg",
"title": "Lathmar Holi in Barsana"
},
{
"url": "/media/images/Lathmar_holi_20.original.jpg",
"title": "Lathmar Holi in Barsana"
}
]
]
},
I'm using this code to get the "url" array. Plz correct me ?
NSArray *imageUrlArray = [[self.jsonData objectAtIndex:indexPath.row]objectForKey:#"cover_url"];
NSLog(#"IMAGE URL ARRAY:%#",imageUrlArray);
NSString *imageUrl = [imageUrlArray valueForKey:#"url"];
NSLog(#"IMAGE URL:%#",imageUrl);
To view the JSON structure - http://jsonviewer.stack.hu/
NSMutableArray* imageurlArray = [NSMutableArray new];
NSArray* jsonArray = jsonData[#"pages"];
for (int i = 0; i<[jsonArray count]; i++) {
NSArray* coverUrlArray = jsonArray[i][#"cover_url"];
for (int t = 0; t< [coverUrlArray count]; t++) {
NSArray* UrlArray = coverUrlArray[t];
for (int x = 0; x<[UrlArray count]; x++) {
[imageurlArray addObject:UrlArray[x][#"url"]];
}
}
}
NSLog(#"imageurlArray: %#", imageurlArray);
//imageurlArray contains all url
//In cell for row at indexpath --> use imageurlArray[indexPath.row];
You have array wrappped by another array.
So, use this direction:
NSDictionary *json=//..initialized
NSArray *pages = [json valueForKey#"pages"];
NSDictionary *page = [pages objectAtIndex:0];
NSArray *ar1 = [page valueForKey#"cover_url"];
NSArray *ar2 = [ar1 objectAtIndex:0];
NSDictionary *elem = [ar2 objectAtIndex:0];
NSString *value = [elem valueForKey#"url"];
I would suggest using Mantel or JSONModel libraries for parsing objects and having decent DTOs.
When you deal with something like this, i suggest putting the complete json in http://jsonviewer.stack.hu/ so you can see the correct structure without getting confused.
Then it's just a matter of digging. When you see { }, you add a dictionary, when you see [ ], you add an array, until you reach your url object :)
I'm not writing the code because it is pretty trivial, just a mix of objectForKeys for dictionaries and objectAtIndex for arrays.
The last layers are just objects, so they're handled like any other object.
If you're confused about json, I suggest you try giving your json-parser a simple json (you hard core it yourself just above, its really just for testing).
Small advice :
Give it a simple array of 1 object, then 2, then put the array in a dict, then two, etc. and you keep making the json more complex until you really understand how it works. Then you'll eventually have a fake json just like your real one, and you can remove the fake and use the real one :)
Other advice :
There are many json parsing libraries that let you create the object model, where you can create (for example) a Page object that has an ID, a title, a cover URl, etc. that matches the JSON structure, and then you just tell the parser " make that JSON a Page!" and voilà, you have a Page. I don't know any of those json libraries in ios, but people will surely link it here, so try it out ! They're super easy to use and make json parsing really straightforward. And also, you don't have to map everything manually like you're doing ;)
Related
This question already has answers here:
Maintaining the order while iterating a NSDictionary
(3 answers)
Closed 3 years ago.
I am getting a dictionary of the following format :
[
{
"position": "1",
"name": "Jaen",
"group": "Student",
"Address": "Delhi"
},
{
"position": "2",
"name": "Jaen",
"group": "Student",
"Address": "Delhi"
},
{
"position": "1",
"name": "Jaen",
"group": "Teacher",
"Address": "Delhi"
}
]
Basically, I want to group them around the key named "group".I have to create a dictionary in the following format to populate data in my UI.
[
{
"Student": [
{
"position": "1",
"name": "Jaen",
"group": "Student",
"Address": "Delhi"
},
{
"position": "2",
"name": "Jaen",
"group": "Student",
"Address": "Delhi"
}
],
"Teacher": [
{
"position": "1",
"name": "Jaen",
"group": "Teacher",
"Address": "Delhi"
}
]
}
]
the order of the Groups should be maintained ie Student should come before Teacher. But when I am printing dictGroupField it is giving random results in terms of order.
How can i maintain the order?
Please find the code below that I was using :
#property (strong, nonatomic) NSMutableDictionary *dictGroupField;
-(void)loadFieldData {
_dictGroupField = [[NSMutableDictionary alloc] init];
NSMutableArray *arrayFields = [self getArrayFields];
for (NSDictionary *dictT in arrayFields) {
NSString *strGroup = [dict valueForKey:#"group"];
if ([_dictGroupField valueForKey:strGroup] == nil) {
NSMutableArray *arrGroup = [[NSMutableArray alloc] init];
[arrGroup addObject:dict];
[_dictGroupField setObject:arrGroup forKey:strGroup];
} else {
NSMutableArray *arrGroupExist = [_dictGroupField valueForKey:strGroup];
[arrGroupExist addObject:dict];
[_dictGroupField setObject:arrGroupExist forKey:strGroup];
}
}
}
You can't maintain it order. Dictionaries are unordered collections of key-value associations. See more Docs
I am trying to store a list of changes made to a Vertex in the Vertex itself. Ideally I would want something like this:
{
"id": "95fcfa87-1c03-436d-b3ca-340cea926ee9",
"label": "person",
"type": "vertex",
"log": [{
"user": "user#user.dk",
"action": "update",
"timestamp": "22-03-2017",
"field": "firstName",
"oldValue": "Marco"
}
]
}
Using this method chain I am able to a achieve the following structure
graph.addV('person')
.property('firstName', 'Thomas')
.property(list, 'log', '22-03-2017')
.properties('log')
.hasValue('22-03-2017', '21-03-2017')
.property('user','user#user.dk')
.property('action', 'update')
.property('field', 'firstName')
.property('oldValue', 'Marco')
{
"id": "95fcfa87-1c03-436d-b3ca-340cea926ee9",
"label": "person",
"type": "vertex",
"properties": {
"firstName": [{
"id": "f23482a9-48bc-44e0-b783-3b74a2439a11",
"value": "Thomas"
}
],
"log": [{
"id": "5cfa35e1-e453-42e2-99b1-eb64cd853f22",
"value": "22-03-2017",
"properties": {
"user": "user#user.dk",
"action": "update",
"field": "firstName",
"oldValue": "Marco"
}
}
]
}
}
However this seems overly complex, as I will have to store a value and add properties to it.
Is it possible to add anonymous objects (i.e. without id and value) with the above mentioned data?
Not an actual solution to storing proper objects in a history log, but if you just use it as a log and don't have to access or query it by its properties, you could just put the serialised JSON in the value?
Something like along these lines should approximate the structure you're requesting:
dynamic entry = new JObject();
entry.user = "user#user.dk";
entry.action = "update";
entry.timestamp = "22-03-2017 12:34:56";
entry.field = "firstName";
entry.oldValue = "Marco";
graph.addV('person')
.property('firstName', 'Thomas')
.property(list, 'log', entry.ToString());
{
"id": "95fcfa87-1c03-436d-b3ca-340cea926ee9",
"label": "person",
"type": "vertex",
"properties": {
"firstName": [{
"id": "f23482a9-48bc-44e0-b783-3b74a2439a11",
"value": "Thomas"
}
],
"log": [{
"id": "5cfa35e1-e453-42e2-99b1-eb64cd853f22",
"value": "{\"user\":\"user#user.dk\",\"action\":\"update\",\"timestamp\":\"22-03-2017\",\"field\":\"firstName\",\"oldValue\":\"Marco\"}"
}
]
}
}
These log entries can easily be read, deserialised, used, and presented, but will not do much for queriability.
I have a problem with sending a JSON response from UITableView into another UITableView.
I want to send the Products array like in the code below into another UITableViewController based on the selected row on the TableView, but when I log the value in didSelectRowAt it returns nil.
So here's the JSON return.
{
"error_description": [],
"results": [
{
"id": 2,
"name": "Ernser, Kilback and Kreiger LLC",
"address": "48788 Adaline Ville 7634 Bertram Shoal",
"contact_person": "Coralie Schaden",
"mobile_number": "(238) 076-0562",
"image": {
"url": null,
"thumb": {
"url": null
},
"medium": {
"url": null
},
"small": {
"url": null
},
"icon": {
"url": null
}
},
"registered_at": "2017-01-10T04:16:52.621Z",
"products": [
{
"id": 21,
"name": "Fantastic Rubber Car",
"image": {
"url": null,
"thumb": {
"url": null
},
"medium": {
"url": null
},
"small": {
"url": null
},
"icon": {
"url": null
}
},
"points": 0,
"merchant_id": 2,
"created_at": "2017-01-10T04:16:52.630Z",
"updated_at": "2017-01-10T04:16:52.636Z"
},
{
"id": 22,
"name": "Mediocre Plastic Shirt",
"image": {
"url": null,
"thumb": {
"url": null
},
"medium": {
"url": null
},
"small": {
"url": null
},
"icon": {
"url": null
}
},
"points": 15,
"merchant_id": 2,
"created_at": "2017-01-10T04:16:52.819Z",
"updated_at": "2017-01-10T04:16:52.827Z"
},
]
}
This is a part of my code for getting the response.
I used the Alamofire
var merchantModel: Merchant!
var merchantArr = [Merchant]()
var productArr = [Product]()
var productModel : Product?
.....
case .success:
let json = JSON(data: response.data!)
for result in json["results"].arrayValue{
guard let merchantID = result["id"].number, let merchantName = result["name"].string, let merchantAddress = result["address"].string, let contactPerson = result["contact_person"].string, let mobilenumber = result["mobile_number"].string else{
return
}
self.merchantModel = Merchant(merchantID: merchantID, merchantName: merchantName, merchantAddress: merchantAddress, contactPerson: contactPerson, mobileNumber: mobilenumber, merchantImage: contactPerson)
let isSuccessfulSave = NSKeyedArchiver.archiveRootObject(self.merchantModel!, toFile: Merchant.ArchiveURL.path)
if !isSuccessfulSave {
print("Failed to save sender...")
}
for prodArr in result["products"].arrayValue{
print("prodArr:\(prodArr)")
guard let prodID = prodArr["id"].number, let prodName = prodArr["name"].string,
let points = prodArr["points"].number else{
return
}
self.productModel = Product(productID: prodID, productName: prodName, productPoints: points)
}
self.merchantArr.append(self.merchantModel!)
self.productArr.append(self.productModel!)
self.merchantModel.loadMerchant()
self.tableView.reloadData()
}
Swift is not javascript, and JSON is not the simplest way to handle the data in this language.
You'd probably prefer to transform your JSON data into Foundation objects, manipulate them, create UITableView with them... And when you'll need to have the JSON format again, you transform those Foundation objects back to JSON.
There are a lot of ways to achieve that, and some amazing third-party libraries to do it very easily. However for a start I encourage you to have a look at Apple's resources :
NSJSONSerialization
Working with JSON in Swift
I am new to iOS and I want to parse data but it is so complex, I don't know how to parse it. Below given is the json data.
{
"response_code": 200,
"last_updated": {
"date": "2015-12-27",
"time": "01:32:13"
},
"trains": [
{
"train": {
"number": "04921",
"start_time": "04:45",
"name": "SRE-UMB MEMU SPECIAL",
"type": "HSP"
},
"dest": {
"code": "UMB",
"name": "AMBALA CANT JN"
},
"source": {
"code": "SRE",
"name": "SAHARANPUR"
}
},
{
"train": {
"number": "04922",
"start_time": "20:45",
"name": "UMB-SRE MEMU SPECIAL",
"type": "HSP"
},
"dest": {
"code": "SRE",
"name": "SAHARANPUR"
},
"source": {
"code": "UMB",
"name": "AMBALA CANT JN"
}
}
]
}
{ , , } - it's a dictionary
[ , , ] - it's an array
In your case you get:
First level - dictionary with keys response_code, last_updated, trains.
Where:
response_code - value
last_updated - dictionary with keys date, time
trains - array of dictionaries with keys train, dest, source
etc.
Use the NSJSONSerialization class, it's easy.
For example, in Objective-C:
id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
if (jsonObject) {
// jsonObject is an NSArray or NSDictionary representation of the data that you can now do something with
}
I have an iOS application which parses a JSON feed provided by Google Plus. This JSON feed contains links, titles, etc for posts on a Google Plus profile.
The JSON file in certain parts has an array called "attachments" and that array has the image URL which I am parsing.
The problem is that that array is not always present, so sometime its available with the image URL and sometime its not even there.
As a result of this, when I parse for the image URL my iOS application crashes because the array it is looking for is not always present.
So how can I test to see if the array is present before deciding to parse for the image URL. I tried to make a simple if-statement, but it doesn't seem to work. Here it is:
if ([[[episodes objectAtIndex:index] valueForKey:#"object"] valueForKey:#"attachments"] == [NSNull null]) {
NSLog("No image to parse.");
}
else {
// parse image link
}
Here is the JSON file:
{
"kind": "plus#activity",
"etag": "\"9Q4kEgczRt3gWehMocqSxXqUhYo/uQcxIDsySGhlI5hMFHcxjuBhM9k\"",
"title": "",
"published": "2013-02-24T22:30:25.159Z",
"updated": "2013-02-24T22:30:25.159Z",
"id": "z13jgdihsvnytdttc23hxdz5ypfsjnzsb",
"url": "https://plus.google.com/102757352146004417544/posts/7psQLdwS2F7",
"actor": {
"id": "102757352146004417544",
"displayName": "Daniel Sadjadian",
"url": "https://plus.google.com/102757352146004417544",
"image": {
"url": "https://lh4.googleusercontent.com/-EF0LibpIsEY/AAAAAAAAAAI/AAAAAAAAALQ/2nt32bqYBtM/photo.jpg?sz=50"
}
},
"verb": "post",
"object": {
"objectType": "note",
"content": "",
"url": "https://plus.google.com/102757352146004417544/posts/7psQLdwS2F7",
"replies": {
"totalItems": 0,
"selfLink": "https://www.googleapis.com/plus/v1/activities/z13jgdihsvnytdttc23hxdz5ypfsjnzsb/comments"
},
"plusoners": {
"totalItems": 0,
"selfLink": "https://www.googleapis.com/plus/v1/activities/z13jgdihsvnytdttc23hxdz5ypfsjnzsb/people/plusoners"
},
"resharers": {
"totalItems": 0,
"selfLink": "https://www.googleapis.com/plus/v1/activities/z13jgdihsvnytdttc23hxdz5ypfsjnzsb/people/resharers"
},
"attachments": [
{
"objectType": "video",
"displayName": "SGU - The Game Has Changed!",
"content": "Send this video to your friends to spread the word about the upcoming SyFy marathon. This very well may be our last chance to save the show. If you're in the...",
"url": "http://www.youtube.com/watch?v=WtHusm7Yzd4",
"image": {
"url": "https://lh3.googleusercontent.com/proxy/z9shhK2d39jM2P-AOLMkqP2KMG2DjipCWlcPeVPaRvHkfj-nmxkxqZfntAVMoV88ZOuroRHIvG4qs-K0SaMjQw=w506-h284-n",
"type": "image/jpeg",
"height": 284,
"width": 506
},
"embed": {
"url": "http://www.youtube.com/v/WtHusm7Yzd4?version=3&autohide=1",
"type": "application/x-shockwave-flash"
}
}
]
},
"provider": {
"title": "Google+"
},
"access": {
"kind": "plus#acl",
"description": "Public",
"items": [
{
"type": "public"
}
]
}
},
Thanks for your time, Dan.
UPDATE:
Just assign that to array and check the array is nil.
NSMutableArray *attachments = [[[episodes objectAtIndex:index] valueForKey:#"object"] valueForKey:#"attachments"];
if (!attachments) {
NSLog("No image to parse.");
}
This will work.
I don't see the problem (please post your error details) but when dealing with JSON, I like to use a category IfNullThenNil. Your code would look like:
if ( [ [ episodes[index] valueForKeyPath:#"object.attachments" ] ifNullThenNil ]
{
// parse image link
}
else
{
NSLog(#"No image to parse.\n");
}
Here's the category on NSObject/NSNull
#implementation NSObject (IfNullThenNil)
-(id)ifNullThenNil
{
return self ;
}
#end
#implementation NSNull (IfNullThenNil)
-(id)ifNullThenNil
{
return nil ;
}
#end