RestKit Object Mapping with large number of properties - objective-c

I have used RKObjectMapping for parsing my JSON response using RestKit.
For ex:.
RKObjectMapping *menuItemMapping = [RKObjectMapping mappingForClass:[MenuCategoryItem_arr class]];
[menuItemMapping addAttributeMappingsFromArray:#[#"item_id",
#"name",
#"item_description",
#"price",
#"offer_price"]];
I have used [RKObjectManager postObject:path:parameters:success:failure:].
This all works fine there's no issue with these mechanisms.
My question is what if i have large number of properties in a class? lets say 50 or 60? how would you map these number of properties in a shorter way?
I have an Rest API which may have more than 40 properties? do i have to define all attribute using addAttributeMappingsFromArray:? or is there any other way?
Thanks in advance

Related

Objective C - JSON to CoreData with category relation [duplicate]

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

RestKit Basic K-V Mapping

I have a JSON payload that is being returned from my server and is structured like this:
{"users":[users]}
Using a simple RKObjectMapping and RKResponseDescriptor, I'm able to successfully map this JSON into a collection of User objects when I use getObjectsAtPath, but now I'd like to make a slight modification to the JSON server-side. Namely, I'd like to add a key-path
{"users":[users], "more":true}
where the key-path "more" indicates whether there are more users to load that are not included in the "users" array. The problem I'm having is that I can't find a simple way to access the value of this "more" key-path. Ideally, I'd like to define a Mapping and Response Descriptor that map "more" into a BOOL (or NSNumber), but I'm having trouble figuring out how to do this. Adding a mapping like
RKObjectMapping *moreMapping = [RKObjectMapping mappingForClass:[NSNumber class]]
with ResponseDescriptor
[RKResponseDescriptor responseDescriptorWithMapping:moreMapping pathPattern:pathPattern
keyPath:#"more" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
Doesn't do the trick. Ultimately, in the success block of getObjects, I'd like my RKMappingResult to be structured like so:
#{#"users":[users], #"more":1}
Any tips?
RestKit is based around mapping data into objects, not to objects in the way you're after. The closest you can get is to map the true into an NSNumber inside a dictionary or array. Try:
RKObjectMapping *moreMapping = [RKObjectMapping requestMapping];
[moreMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil toKeyPath:#"more"]];

Objective-C - Json for Game or is there a better way

i have some questions about json! i hope anybody can help me!
I have created a game and now i want to bring some variables out of my Game into a json file!
So i want to ask, is it possible to bring floats and an array
NSArray *points = [NSArray arrayWithObjects:
[NSValue valueWithCGPoint:CGPointMake(50.0, 150.0)],
[NSValue valueWithCGPoint:CGPointMake(350.0, 300.0)],nil];
into a json file?!
Also i want to bring my background-images for the different levels in the json file.
Is it possible to do it with json or anybody know a better way.
It would be great if anybody could tell me. Or anybody know a good tutorial?!
Thanks
If you don't have to serialise the objects to move between environments, then I wouldn't bother with JSON... if you are consuming a web service or something, then they are great... if you have them in values, then I would just store them in a plist assuming you have no interchange.
To answer the question about the background images ... you would simply store the filename/path to the image. That way, multiple files or levels could potentially refer to the same asset.
JSON supports hashes (dictionaries) and arrays as containers, which can contain hashes, arrays, numbers, strings and booleans within them. So to capture that data you might have a structure like this:
{
"points":[
[50.0, 150.0],
[350.0, 300.0]
]
}
And read it back with something like this:
NSArray *pointsData = [json objectForKey:#"points"];
NSArray *points = [NSArray arrayWithObjects:
[NSValue valueWithCGPoint:CGPointMake(
[[pointsData objectAtIndex:0] objectAtIndex:0],
[[pointsData objectAtIndex:0] objectAtIndex:1]
)],
[NSValue valueWithCGPoint:CGPointMake(
[[pointsData objectAtIndex:1] objectAtIndex:0],
[[pointsData objectAtIndex:1] objectAtIndex:1]
)],
nil];
Cocoa supports only these type in its JSON support.
NSNumber (integer, float, boolean)
NSString
NSArray
NSDictionary
Whatever you want to save/load, you should organize your data to use only those types. Direct use of NSValue is not supported, so you need to make something like this.
NSDictionary* point = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat:444f],
#"x",
[NSNumber numberWithFloat:555f],
#"y",
nil];
And save the dictionary.
In addition, you also can use equivalent new literal syntax which is mainly designed for Property List.
NSDictionary* point = #{ #"x" : #444f, #"y": #555f };
This is equal to above example.
CAVEAT: All keys of NSDictionary must be NSString when you are saving the data to JSON or Property List.
Consider using of Property List
If you are targeting only iOS, Property List is always right and better choice to save/load some small amount of variables. Also Xcode will give you better editor.
Support for JSON in Cocoa is just a subset of the Property List, and mostly similar. So look at the Property List first, and than you will be able to use PLIST or JSON easily. (this is why there's no guidance document for JSON in Cocoa)
Background Images
It is possible to save image data in JSON or Property List, but it is usually not recommended. Because JSON or PLIST need to load at once. This means all file content must be loaded into memory. If you put multiple images in a JSON or PLIST file, it will get bigger up to multiple megabytes easily. And iOS devices doesn't have much memory, so your program may crash.
So it is recommended to store only path to image file in JSON or PLIST file - as like #JoelMartinez indicates -, and load the each image file directly from the path.

How to update a posted object in RestKit with different primary key attributes?

I'm posting objects on a server as JSON that consists of a few attributes and an ID that is the primary key attribute. I'm also using Core Data to save all the objects locally.
The problem is that when I first create the object to POST I know all the attributes but the unique ID. The ID is set at server-side, and when I get the response from the server I have ended up with two objects in my database:
One with ID 0, and one with the real ID.
Is there any way to get restkit/coredata to treat these two objects as the same, or alternatively don't save the first object in the database?
You can use the postObject: usingBlock method and assign a target object for the object loader like this.
[[RKObjectManager sharedManager] postObject:myObject usingBlock:^(RKObjectLoader *loader) {
loader.targetObject = myObject;
loader.delegate = self;
loader.objectMapping = [[RKObjectManager sharedManager].mappingProvider objectMappingForClass:[myObject class]];
}
Note that you also have to set the delegate manually in the block of code every time you run the method.

How can I make an sort of multidimensional associative array in objective-c / UIKit?

Problem: I have a set of images, lets say 5. There is an structure that defines an "image object" in the meaning of my context.
Every such image object has this information:
name, of the image file (ie "myImage.png")
xOffsetPx
yOffsetPx
width
height
The images are supposed to be shown on very specific positions in an view, so I need to store all this information in some sort of multidimensional associative array (or similar). The name of the image would be the key or ID.
I stumbled upon something like that a month ago in my 1000 pages objective-c book, but can't find it anymore. Any idea here?
Unless I'm completely misunderstanding the question - why not create an actual object (or struct) out of those properties and store that as the value in your dictionary?
The most simple way would be to just use a dictionary:
NSMutableDictionary *images;
NSDictionary *myPictureAttributes = [NSDictionary dictionaryWithObjects:
[NSArray arrayWithObjects:[NSNumber numberWithFloat:30],
[NSNumber numberWithFloat:10],
[NSNumber numberWithFloat:15],
[NSNumber numberWithFloat:15], nil],
forKeys:[NSArray arrayWithObjects:#"xOffsetPx",
#"yOffsetPx",
#"width",
#"height", nil]];
[images setObject:myPictureAttributes forKey:#"myImage.png"];
You would probably want your attributes to be constants of some kind so that compiler can warn you if you make a spelling error. You could also have a simple data object class with a few properties on it, then set those and add the object directly to the dictionary. There are a number of other ways to solve this problem, depending on your exact requirements, but NSDictionary is the basic collection class in Cocoa for associative arrays.