access to different levels of a json file - objective-c

how do I access the contents of group?
Currently, I can access bookmarks and blog.
I think the two characters after group generate problem of reading.
Here's code that selects the data from the json file to display data
NSDictionary *feed = [jsonObjects objectForKey:#"object"];
NSArray *entries = [feed objectForKey:#"bookmarks"];
for (NSDictionary *item in entries)
{
[item objectForKey:#"SomeDataIdentifierOfBookmarks"]
}
Here is the JSON file read by a NSMutableArray
EDIT REAL DATA JSON
{"object":
{"blog":[{"guid":181,"type":"object","subtype":"4","time_created":"","time_updated":"","container_guid":"180","owner_guid":"180","site_guid":"1","title":"ugyt","description":"scsa","url":"http://s210678217.onlinehome.fr/blog/view/181/ugg-sito-ufficiale-italiavyt"}],
"bookmarks":[{"guid":82,"type":"object","subtype":"9","time_created":"1372072736","time_updated":"1372072910","container_guid":"81","owner_guid":"33","site_guid":"1","title":"internet - ","description":"","url":"hr"},
{"guid":75,"type":"object","subtype":"9","time_created":"1371728924","time_updated":"1371728924","container_guid":"64","owner_guid":"52","site_guid":"1","title":" du ","description":"p>","url":"htts"},
{"guid":64,"type":"group","subtype":"0","time_created":"1371728148","time_updated":"1372068044","container_guid":"33","owner_guid":"33","site_guid":"1","name":" yvelines","description":"Le.</p>","url":"http://ses"}
]
]
}
Thanks

This is not close to being valid JSON. Use http://jsonlint.com to make sure you have valid inputs before worrying about your code for unpacking the data. You have multiple un-closed arrays (the "[" character starts an array, "]" ends it, and at least one missing comma (before "bookmarks"). It's hard to tell what is wrong with this JSON, because there are enough errors that the intent is not clear.
Your code for accessing the contents is mostly fine, except that "SomeDataIdentifierOfBookmarks" isn't a key that is in your JSON—I presume you mean that would be replaced with an actual value.
Edit: Your pasted actual JSON is trying to close the "object" object with a square bracket rather than a curly bracket. jsonlint will turn those errors up quickly.

Related

Make Whole Request UTF-8 from NSURLSession

I am making a simple NSURLSession GET request and i am returned the right data and i am able to serialize it up to one point where the data is no longer UTF-8 so i am unable to call keys of the children.
My data looks like this:
[
{
"GeoJsonData":"{\"type\":\"Feature\",\"properties\":{},\"geometry\":{\"type\":\"LineString\",\"coordinates\":[[-119.1968536376953,35.5229358991794],[-119.19696092605591,35.52019399894053],[-119.19206857681274,35.520141605030304],[-119.19204711914062,35.52003681710729],[-119.18736934661865,35.52007174643016],[-119.18730497360228,35.52213254957543],[-119.18839931488039,35.52215001378275],[-119.18842077255249,35.522813650845336],[-119.19696092605591,35.522918435143076]]}}",
"GeoJsonCenter":"{\"lat\":35.52148635814335,\"lng\":-119.1921329498291}"
},
{
"GeoJsonData":"{\"type\":\"Feature\",\"properties\":{},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-112.42687225341795,33.49409462250672],[-112.42678642272949,33.47605511894646],[-112.42549896240234,33.47605511894646],[-112.42103576660156,33.48822503770075],[-112.41022109985352,33.49438093353938],[-112.42687225341795,33.49409462250672]]]}}",
"GeoJsonCenter":"{\"lat\":33.48521802624292,\"lng\":-112.41854667663574}"
}
]
As you can see there are alot of escape characters in there and i have 85 objects in this array i need to iterate over and once i get down to the children of these objects i am not able to call those objects.
example of my code:
NSMutableArray *geoJSONData = [[NSMutableArray alloc] init];
for (NSDictionary *item in jsonArray){
[geoJSONData addObject:[item objectForKey:#"GeoJsonData"]];
}
for (NSDictionary *item in geoJSONData) {
NSLog(#"%#", [item objectForKey:#"coordinates"]);
}
the last NSLog blows up the console because it is not able to find that key "coordinates" because it is wrapped with escaped characters and i need to get those out.
Has anyone ran into this issue and whats the best way to solve this so i can have my object working fully serialized as JSON.
any help is greatly appreciated, im just getting back into Objective-c from AngularJs and last time i worked with Objective-C i used NSUrlRequest...so things have changed.
If the data that you shown is the real representation of it then you have a small issue. The value for key GeoJsonData is not an object but a string. In other words it's an object that was serialized using JSON.stringify() and added to the parent object. Quite a strange construction, that's why I'm asking if that is the real JSON representation sent by the server.
What you'll need to do before trying to access the key coordinates is to JSON parse that string to get a valid object back so you can access it's properties as a normal NSDictionary, write now is just a string.
Just use NSJSONSerialization class to decode your GeoJsonData.

Suggestions to Process Complex + Large Data File

I have a very large and complex data file (.txt, see snippet below) of about 10MB and would like to know the best way to store it and access it later on.
My app currently uses core data for storage of other entities but I don't see how I can create an entity from this type of data file because of its complexity.
This file is divided as follows:
First line of each major section begins with an A| and means a new 'airway' to be defined. Then, is it's name, so in the example below we have the airway named V320 and another named V321. On the following lines, we have important data, the 'points'/waypoints which make up this airway. Each one has a name, and coordinates. So the first one here is PLN at 45.63N and -84.66W (coordinates). Then, from there the next one is LORIW at 45.35N and -84.92W, from LORIW we go to IROTO, and so on...
NOTE: There may be two, three, maybe even 4 airways with the same 'name' like V320 for example has 3...but each one is in it's own part of the map.
The other values there are irrelevant such as the numbers after the coordinate pair.
In essence, I need all this so that I can then draw lines on my map (GMSPolyLine using Google map SDK) which goes through all these points for each airway and then to create GMSMarkers(google version of MKAnnotation) for each waypoint which the user can tap.
I can handle the drawing of lines/markers on the map but the difficult part for me to visualize is the manipulation of this data and making it easier to access.
Let me know if you have any questions.
A|V320|20
S|PLN|045630647|-0084664108|LORIW|045352072|-0084924214|0|219|1998
S|LORIW|045352072|-0084924214|IROTO|045188989|-0085075111|219|219|1168
S|IROTO|045188989|-0085075111|ADENO|045030644|-0085220425|219|219|1132
S|ADENO|045030644|-0085220425|TIDDU|044877978|-0085359767|215|215|1090
S|TIDDU|044877978|-0085359767|SKIPR|044831714|-0085401772|215|215|330
.....
A|V321|29
S|PZD|031655206|-0084293100|KUTVE|031866950|-0084451303|0|329|1505
S|KUTVE|031866950|-0084451303|DUVAT|031948772|-0084512695|329|329|582
S|DUVAT|031948772|-0084512695|LUMPP|032041158|-0084582139|329|329|657
S|LUMPP|032041158|-0084582139|PREST|032176375|-0084684117|329|329|963
S|PREST|032176375|-0084684117|CSG|032615253|-0085017631|326|326|3129
S|CSG|032615253|-0085017631|JALVO|032722436|-0085064033|326|339|684
.....
Your data exhibits some regularity. If it is predictable and consistent, just write a parser that iterates through the file and creates appropriate Core Data entities.
For example, the fact that each new airway is separated by a newline can help you find those. Also, each final waypoint is repeated in the next line unless you are at the end of an airway record. I think you can do this in maybe 20-30 lines of code.
On your development machine (or even on an iPad or recent iPhone, for that matter), even creating a 10MB array in memory (to be parsed) should not be a constraint.
If the data is static, you can use the resulting sqlite database as a read-only persistent store that you can include in your app bundle.
As for the parser, it would be something like this:
NSString *file = [[NSString alloc] initWithContentsOfFile:fileURLString
encoding:NSUTF8StringEncoding error:nil];
NSArray *lines = [file componentsSeparatedByString:#"\n"];
for (NSString *line in lines) {
if (line.length < 1) { continue; }
NSArray *fields = [line componentsSeparatedByString:#"|"];
if ([fields.firstObject isEqualToString:#"A"]) {
// insert new airway object and populate with other fields
}
else if ([fields.firstObject isEqualToString:#"S"]) {
// insert new waypoint object (two for each first line)
// assign as relationship to the current airway
// and to another waypoint as necessary
}
}
[managedObjectContext save:nil];

NSMutableArray Meta-Data when exported to CSV file

Looking for some advice with an iOS application.
Essentially what my app does is generate a CSV file that logs certain events within a period of time. So users can press a button and an entry will be added to the log saying "Event of type X happened at Time T"
The way I'm doing this is by maintaining an NSMutableArray which stores NSStrings. Each event adds a string to the NSMutableArray.
When the user is done with a session, they can "export" the file. I'm using the NSMutableArray's writeToFile; then I use an e-mail interface to send that file as a CSV to a target e-mail.
It all works, except the CSV file that is generated has some meta-data in it. Specifically, I believe at the top of the file I see and at the beginning of each row of cells when opened in excel.
Is this something inherent in the data structure (NSMutableArray) or data type (NSString) that I am using? Is there a way for me to just get the raw data?
I can upload code if need be (I'm not near the work computer now though, so I'm testing the waters to see if there is something simple I can do to stop seeing this meta-data).
Thank you!
CSV is a very simple format. You can separate the strings with semi-colons and then write everything to a file using NSOutputStream.
This code assumes you already have a string array with CSV rows:
NSOutputStream* csvoutput = [NSOutputStream outputStreamToFileAtPath:filepath append:NO];
[csvoutput open];
for (NSString* str in array) {
NSString* tempStr = [str stringByAppendingString:#"\n"]; //new line
NSData *strData = [tempStr dataUsingEncoding:NSUTF8StringEncoding];
[csvoutput write:(uint8_t *)[strData bytes] maxLength:[strData length]];
}
[csvoutput close];
You better create a model class (Event) and fill the array with Event-instances instead of strings. Thats cleaner and more efficient. Then you would create the CSV-strings when exporting to a file.

Objective-C: how to compare 2 PLists

I'm a total newbie to Objective-C and have been tasked with an assignment to compare 2 builds of same app for differences in their Info.plist and Defaults.plist.
I have been able to figure out the steps to read the PLists from app bundle but am having difficulty figuring out how to compare EVERY key in PLists to its counterpart file. For illustration if I need to compare Info.plist between 2 app bundle (lets say build_100 and build_101), how do I recursively go to each key in build_100 and compare the same key in build_101 to verify if they are same or not.
Its easy if both PLists are same because isEqualToDictionary will return TRUE but problem occurs if something in a nested dictionary is different between both the builds.
Going through related queries here, it clear to me that the answer is that I write a recursive method that iterates through both PLists but I'm having a real frustrating time to figure out a way to do this for a nested dictionary like Info.plist.
So I've finally figured this thing out so thought of sharing it with others for future reference. I'm sure there'll be some other lost soul in future looking for something similar (or at least I hope :)).
The way I wrote my code was to:
Read both Plists in NSDictionaries
Treat one Plist as "to be tested" and other as the reference (to compare against) to find out if its a Pass/Fail
Loop through all keys in "to be tested" Plist and compare each one of them in "reference" Plist
When it came to compare an Array or Dictionary, this check (that's the part I was struggling with) had to be a recursive check
The code to write for step #1, 2, 3 is straight forward so I'm going to give the method I wrote for #4 which was the crux of my original question.
This function compareSourceObject() will take 3 arguments:
sourceObject: object to be tested
targetObject: object to compare against
trailPath: string that'll hold the entire path of the key that has failed
- (void)compareSourceObject:(id)sourceObject andTargetObject:(id)targetObject withBreadcrumbTrail:(NSString *)trailPath{
NSString *message = [[NSString alloc] init];
if ([sourceObject isKindOfClass:[NSDictionary class]]){
for(id item in sourceObject){
[self compareSourceObject:[sourceObject objectForKey:item] andTargetObject:[targetObject objectForKey:item] withBreadcrumbTrail:[trailPath stringByAppendingFormat:#"->%#", item]];
}
}
else if ([sourceObject isKindOfClass:[NSArray class]]){
for (int counter=0; counter %d", counter]];
}
}
else if(![sourceObject isEqual:targetObject]){
NSLog(#"Values do not match. Value in \"TestedDicationary\" is (%#) but the reference dict has (%#)", targetObject, sourceObject);
}
}
Hope this helps. Comments/Suggestions/Optimizations are more than welcome.
Take one plist, and interpret the properties as a set (NSSet) of string values, e.g.
:items:0:assets array
:items:0:assets:0:kind string VALUE
Note I am using /usr/libexec/PlistBuddy format to describe a property - path type [value].
Then do the same for the second plist and compare the sets using NSSet functions.

How does one save a list of images in Objective-C

In my code I have an item that is a list of alternating strings and images that I wish to save. I know how to save individual images in their JPEG representations, but is there a simple and efficient way I don't know of in Objective-C to save all these items (or at least the images since I can handle the strings myself) while maintaining their order?
ex: item 1 ("hi", image, "how", image, "are", image), item2("this", image, "is", image)
maintaining item order is not important to me, but the order in the list is. The first thing that comes to mind is simply to save every single image, and have an algorithm to create then remember their imagename and then save and load the text list. Is there an easier way to do this? Can I literally just save the array itself as a plist and be on my merry way? (i've only seen examples of these with strings)
I believe I understand what you're going for. You'd like to save an array of items, each of which contains an array of Objects that contain an image and a string. If this is accurate then you're idea of saving the array to a plist is correct.
In short you would create NSDictionaries of your Objects and save the array of them. Like so:
In your object you'll have a method similar to this:
- (NSDictionary *)dictionaryOfItemData;
{
NSMutableDictionary * mutableDictionary = [[NSMutableDictionary alloc] init];
[mutableDictionary setObject:imageName
forKey:#"imageName"];
[mutableDictionary setObject:UIImagePNGRepresentation([self image])
forKey:#"imageData"];
return mutableDictionary;
}
Then you would save an array of these (or array of arrays, or whatever your desire based on file size concerns, need to load, etc.) like so in the proper place:
[[arrayOfDictionaries description] writeToFile:path
atomically:YES
encoding:NSUTF8StringEncoding
error:NULL];
Which gives you the plist, that you can load and hydrate by creating your image with data and setting the image name from the dictionary.
~Good Luck