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.
Related
I have an app written in dart which uses a channel to call a method in Objective-C. The method needs data in form of an NSArray to act. I am passing this data as Uint8List from dart but in Objective-C, it shows that it's a FlutterStandardTypedData. Is there any way to convert that to an NSArray? Thanks in advance.
You will likely have to copy it out of the FlutterStandardTypedData using something like... (Note that in this example the typed data is doubles - you presumably have bytes)
if let args = call.arguments as? Dictionary<String, Any>,
let au = args["data"] as? FlutterStandardTypedData {
au.data.withUnsafeBytes{(pointer: UnsafeRawBufferPointer) in
let doubles = pointer.bindMemory(to: Double.self)
for index in 0..<Int(au.elementCount) {
// copy to the NSArray
}
}
result(nil)
} else {
result(FlutterError.init(code: "errorProcess", message: "data or format error", details: nil))
}
I'm having issues w/ FlutterStandardTypedData as well. From what i'm reading this should be serialized "auto-magically" on the iOS side as it's a supported data type. I can see on my end, for instance, that the length of the byte buffer is the value i'm expecting. My issue is I cannot seem to access a single value of the byte data in the same method i can see the length value. "Unrecognized selector for FlutterStandardTypedData" whenever i try to access it like an array...I cannot find good documentation either. If i use a simple data type, like string, things work out just fine. I'm only getting burned by the more complex data type(s)...
I figured it out, in the plugin you have to use FlutterStandardTypedData as the data type for the array, and then you can see the .data elements on the native iOS side. Without this data type, coming in to the iOS side i could "see" the data but would get memory exceptions every time i would try to access the data(objects/elements) in the list. Xcode was previously converting my NSArray to a FlutterStandardTypedData in the IDE (even though i specified NSArray NOT FlutterStandard...) auto-magically, but again, erroring out whenever i would try to work w/ the object. Simply changing from NSArray in plugin to FlutterStandardTypedData solved my problem, just took a while to figure out b/c the documentation wasn't very clear (that i came across).
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.
I'm initiating a URL connection and my script is returning the following JSON:
(
1,
{
"id" = <-ID Here->;
hash = <-Hash Here->;
},
(
),
(
) )
All the examples I've seen so far seem to have "ids" or identifiers before respective arrays/dictionaries. Despite searching around, I couldn't find a way to parse this. (i.e. I need to get the first boolean value, the id, the hash, and then the arrays as well (which are empty as of now)).
Sorry if I'm missing something-- I'm new to parsing JSON in Obj-C.Thanks for the help.
The feature I use is built in with the Cocoa libraries: the NSJSONSerialization class.
It provides methods for parsing JSON into a graph, and encoding a graph into JSON. The rules are similar to plists (i.e. basic types plus arrays and dictionaries).
If you have NSData (which you can easily get from a string), you do like this:
NSArray *yourJSONAsObjectGraph = [NSJSONSerialization JSONObjectWithData:yourNSData options:nil error:&err];
Then, with your data above, objectAtIndex:0 would be an NSNumber that you can call boolValue on, objectAtIndex:1 will be an NSDictionary that you can call objectForKey:#"id" (and #"hash"), etc.
See How to use JSON in Objective-C. If you didn't hear about it yet, have a look at SBJSON.
I'm a nwebie in Core Data, i have designed a navigation based application and some of the data i use are created on run time(come from a URL via JSON). I took a few tutorials an searched for almost a day but haven't still realized how to save the incoming JSON data to the Entity (or event?) in my Core Data model. I fetch the data in the DetailViewController class and i need to save this data to Core Data(I have prepared an Entity with 7 properties). Can anyone please help?(If you know a good tutorial or sample code i will be pleased)
EDIT This may be a little specific but i really have trouble with and need just a little help.
My data comes to the app from a kind of restful server(i wrote it in PHP), firstly user enters his/her login informations(which i have saved to the database on server before) and when the response data comes i will use different elements of it in differen views(for example the user_id will be used on a view and the buttonData etc on other views). My question is, how will i save JSON data into my core data model(has tree Entities for the moment). Thanks in advance
Note: I lokked arround a lot but couldn't find any answer&tutorial about an app like mine
The best way to do that would be to create entities corresponding to JSON structure. Easiest was is when each JSON object becomes an entity, and arrays become arrays of entities. Be reasonable, however, and don't introduce too much overkill for JSON subobjects that are essentially part of its superobject.
When you have created entities, you can start off with the parsing and translation. Use some JSON framework (starting from iOS5 there's one from Apple) and parse JSON string into object tree, where root item is either an NSArray or NSDictionary, and subelements will be NSArray, NSDictionary, NSNumber, NSString or NSNull.
Go over them one by one in iterational loops and assign according values to your core data entity attributes. You can make use of NSKeyValueCoding here and avoid too much manual mapping of the attribute names. If your JSON attributes are of the same name as entity attributes, you'll be able to just go over all dictionary elements and parse them into attributes of the same name.
Example
My parsing code in the similar situation was as follows:
NSDictionary *parsedFeed = /* your way to get a dictionary */;
for (NSString *key in parsedFeed) {
id value = [parsedFeed objectForKey:key];
// Don't assign NSNull, it will break assignments to NSString, etc.
if (value && [value isKindOfClass:[NSNull class]])
value = nil;
#try {
[yourCreatedEntity setValue:value forKey:property];
} #catch (NSException *exception) {
// Exception means such attribute is not defined in the class or some other error.
}
}
This code will work in trivial situation, however, it may need to be expanded, depending on your needs:
With some kinds of custom mappings in case you want your JSON value be placed in differently named attribute.
If your JSON has sub-objects or arrays of sub-objects, you will need to detect those cases, for example in setters, and initiate new parsing one level deeper. Otherwise with my example you will face the situation that assigns NSDictionary object to an NSManagedObject.
I don't think it is reasonable to dive into these, more advanced matters in scope of this answer, as it will expand it too much.
I suggest you to use this library : https://github.com/TouchCode/TouchJSON
And then if you want to make a factory to parse json and feed your code data, you can use selectors to call methods to fill all your attributes.
Chances are your JSON data gets converted to an NSDictionary or NSArray (or some combination of the two). Simply extract the key/values from the JSON structure and add them to your entity class.
This lib helps me lot
Features
Attribute and relationship mapping to JSON key paths.
Value transformation using named NSValueTransformer objects.
Object graph preservation.
Support for entity inheritance
Works vice-versa
Specifically, this problem has come to me when I make a request with AFNeworking with JSONkit and receive a (id)JSON with several arrays and dictionaries nested.
If I don't want to modify the data, I don't have any problem:
self.myNSArray = [JSON objectForKey:#"result"];
But if I want to modify the data I must to store it in a mutable variable:
self.myNSMutableArray = [[JSON objectForKey:#"result"] mutableCopy];
The last one doesn't convert nested arrays or dictionaries to mutable data; it works only for first level.
The only way that I have found is on this link recursive mutable objects; but I don't know if there is a best way to resolve this kind of problem.
Thanks in advance.
You could use the CoreFoundation function CFPropertyListCreateDeepCopy with the mutability option kCFPropertyListMutableContainersAndLeaves:
NSArray *immutableArray = [JSON objectForKey:#"result"];
self.myMutableArray = [(NSMutableArray *)CFPropertyListCreateDeepCopy(NULL, immutableArray, kCFPropertyListMutableContainersAndLeaves) autorelease];
On ARC:
CFBridgingRelease(CFPropertyListCreateDeepCopy(NULL, (__bridge CFPropertyListRef)(immutableArray), kCFPropertyListMutableContainersAndLeaves))
really worked. Thanks
brainjam.
Make sure you are taking care of null values in response string, otherwise it will return you nil which causes to horrible results.
(For Eg. Try mutataing response from
http://www.json-generator.com/api/json/get/bQVoMjeJOW?indent=1)
Just place below line when converting API response to JSON Object.
responseString=[responseString stringByReplacingOccurrencesOfString:#"\":null" withString:#"\":\"\""];//To Handle Null Characters
//Search for below line in your parsing library and paste above code
data = [responseString dataUsingEncoding:NSUTF8StringEncoding];
So there will be no null characters in your JSON object, hence no issue with using CFPropertyListCreateDeepCopy.
Cheers!!