Restkit OM2 relationship mapping - iphone

Im using Restkit OM2 to take in a json and map to objects on iphone.
Im currently confused on how to structure the mappings and could do with some help.
Below is an example json file
{
-magic_verbs: [
-{
lemma: "work"
position: 5
score: "0.75"
value: "working"
}
-{
lemma: "head"
position: 0
score: "0.75"
value: "heading"
}
],
magic_advs: [
-{
lemma: "not"
position: 2
score: "0.6"
value: "not"
}
-{
lemma: "just"
position: 2
score: "0.6"
value: "just"
}
]
}
i only need the lemma and value fields from each of these. so for example the verb class contains
#interface Verbs : NSManagedObject {
}
#property (nonatomic,retain) NSString *lemma;
#property (nonatomic,retain) NSString *value;
#end
#implementation Verbs
#synthesize lemma,value;
#end
then i read in the json and create the mappings with below code
objectManager = [RKObjectManager objectManagerWithBaseURL:#"http://localhost:3000"];
objectManager.objectStore = [RKManagedObjectStore objectStoreWithStoreFilename:#"RKRelationshipMappingExample.sqlite"];
[RKObjectManager setSharedManager:objectManager];
RKObjectMappingProvider* provider = [[RKObjectMappingProvider new] autorelease];
RKObjectMapping* verbMapping = [RKObjectMapping mappingForClass:[Verbs class]];
[verbMapping mapKeyPath:#"lemma" toAttribute:#"lemma"];
[verbMapping mapKeyPath:#"value" toAttribute:#"value"];
[provider setMapping:verbMapping forKeyPath:#"magic_verbs"];
[[RKObjectManager sharedManager] loadObjectsAtResourcePath:#"/api/users/1/magic_words" objectMapping:verbMapping delegate:self];
I have done the same for the adjs mapping. I also have a class called words that contains 2 nsarrays that is to contain the object mapping data. but im unsure how to implement this and link them up correctly.
#interface Words : NSObject {
NSArray *_verbs;
NSArray *_adjs;
}
#property (nonatomic, retain) NSArray *verbs,*adjs;
#end
any help and guidance on this is appreciated. I have looked at the example in catalog project and have been able to get that running but havent been able to master the concept to apply it to my own json files.
thanks
G

I suggest you to look at the new documentation of OM 2.0 that is in the Github page here
if you haven't noticed yet. It clearly lays out on how to map your JSON to an object.

Related

RestKit: mapping of dynamic attribute (not a NSDictionary as in the example)

I'm using RestKit in my iOS project, and figured non-trivial problem and can't find solution for it.
I have a json:
[{
"name": "restkit",
"downloads": 2
},
{
"name": "restkit",
"rating": 10.0
}]
and data model: Model.h
#interface Model : NSObject
#property (nonatomic, strong) NSString * name;
#property (nonatomic, strong) NSString * key;
#property (nonatomic, strong) NSString * value;
#end
Those JSON objects loaded in one array, and one of the attributes is a "dynamic" attribute.
After mapping performed in a RestKit I want to be able to have 2 records:
name: "restkit", key: "downloads", value: 2
name: "restkit", key: "rating", value: 10.0
Question: how to map JSON in the beginning into 2 NSObjects as shown in the example above?
This is how I initialize mapping using RestKit and firing requests:
// during app initialization I setup mappings:
RKObjectMapping *modelMapping = [RKObjectMapping mappingForClass:[Model class]];
[metricDataMapping mapKeyPath:#"name" toAttribute:#"name"];
...... -- something should go here to support that dynamic stuff
[[RKObjectManager sharedManager].mappingProvider addObjectMapping:metricDataMapping];
// in the view controller when loading data
[[RKObjectManager sharedManager] loadObjectsAtResourcePath:url usingBlock:^(RKObjectLoader *loader){
loader.objectMapping = [[RKObjectManager sharedManager].mappingProvider objectMappingForClass: [MetricData class]];
loader.onDidLoadObjects = ^(NSArray * objects){
self.dataArray = objects;
};
}];
The problem, is that keys "downloads" and "rating" are dynamic, and it could be any word. I need to parse that 'on-the-fly' and show in UI.
Restkit does support such behavior, but only for nested dictionaries.
You can access the dynamically named properties using key-value coding. After you had made an NSDictionary out of the JSON, do this:
[self setValue:[dictionary objectForKey:#"downloads"] forKey:#"downloads"];
etc.
I did use key-value validation on the model triggered by RestKit to set correct metric key and value to the generic key I want.

Serializing a nested object when posting from iOS to Rails app

Hoping to get a little push in the right direction. I am having trouble getting a nested object to serialize properly when I POST to my rails app using RestKit. I have the following mappings:
RKObjectMapping *cartSerializationMapping = [RKObjectMapping mappingForClass:[TOCart class]];
[cartSerializationMapping mapKeyPath:#"place.placeID" toAttribute:#"order[external_id]"];
//map the line items serialization mapping
RKObjectMapping *lineItemSerializationMapping = [RKObjectMapping mappingForClass:[TOLineItem class]];
[lineItemSerializationMapping mapKeyPath:#"itemID" toAttribute:#"itemID"];
[lineItemSerializationMapping mapKeyPath:#"name" toAttribute:#"name"];
[[RKObjectManager sharedManager].mappingProvider setSerializationMapping:lineItemSerializationMapping forClass:[TOLineItem class]];
//add relationship bw line items to TOLineItem
[cartSerializationMapping mapKeyPath:#"line_items" toRelationship:#"order[line_items]" withMapping:lineItemSerializationMapping serialize:YES];
[[RKObjectManager sharedManager].mappingProvider setSerializationMapping:cartSerializationMapping forClass:[TOCart class]];
After posting to the server, serialization works for the parent object but not for the nested line_item object:
Started POST "/orders" for 127.0.0.1 at 2011-11-16 04:05:58 -0800
Processing by OrdersController#create as JSON
Parameters: {"order"=>{"line_items"=>["<TOLineItem: 0x8aafdb0>"], "external_id"=>"4ae8a535f964a52024b121e3"}}
I want the line_item to serialize to itemID and name etc...
Did I set my mappings incorrectly?
Thanks!
UPDATE:
My TOCart class:
#import <Foundation/Foundation.h>
#class TOPlace;
#interface TOCart : NSObject
{
NSNumber *cartID;
TOPlace *place; //post to external id
NSString *state;
NSMutableArray *line_items;
}
#property (nonatomic, retain) NSNumber *cartID;
#property (nonatomic, retain) TOPlace *place;
#property (nonatomic, retain) NSString *state;
#property (nonatomic, retain) NSMutableArray *line_items;
#end
I always define my mapping to map from API to entities & then create the serialization mapping with [myMappingFromApi inverseMapping] selector. You can find further details in my answer to somewhat different question, but definitely related: RestKit: How does one post an array of objects?.

RestKit: how to make a mapping for varying key names

I'm trying to make a dynamic mapping for a bit weird structured JSON.
I have "array mapped to object" sort of thins so that array indices
ake keys e.g.:
{
"0": {object},
"1": {another object},
"2": {yet another object},
...
}
All objects are of the same type so they can be parsed using the same
mapping, but how to deal with varying key names?
Check out the section on "Handling Dynamic Nesting Attributes" in the Object Mapping docs.
He walks through an example (copied here) with the JSON:
{ "blake": {
"email": "blake#restkit.org",
"favorite_animal": "Monkey"
}
}
Corresponding to the User class:
#interface User : NSObject
#property (nonatomic, retain) NSString* email
#property (nonatomic, retain) NSString* username;
#property (nonatomic, retain) NSString* favoriteAnimal;
#end
Which, you'll notice, the username property corresponds to the key of the JSON.
In order to map it, he uses a special parenthesis syntax to indicate that they key itself is a property:
RKObjectMapping* mapping = [RKObjectMapping mappingForClass:[User class] ];
[mapping mapKeyOfNestedDictionaryToAttribute:#"username"];
[mapping mapFromKeyPath:#"(username).email" toAttribute:"email"];
[mapping mapFromKeyPath:#"(username).favorite_animal" toAttribute:"favoriteAnimal"];
Hope this helps!

Convert 2D NSMutableArray in JSON format - JSONKit

I have the following array
NSMutableArray* answers;
Each element of answers is itself an array of objects.
I need to convert the above 2D array into appropriate JSON format (using the JSONKit framework), so that it can be passed to a php application and decoded thereafter...
The individual objects have the following structure:
#interface Answer : NSObject {
//NSString* answerId;
NSString* answer;
NSString* questionId;
}
//#property (nonatomic, retain) NSString* answerId;
#property (nonatomic, retain) NSString* answer;
#property (nonatomic, retain) NSString* questionId;
#end
That is that each element of answers is an array of Answer Objects. essentially what I need is to encode the relevant data in each answer object into JSON format using the JSONKit framework so that it can be posted to a php app and decoded....
Essentially I need somthing of the form:
{{"answer":"1","questionId":"1"}, {{"answer":"5","questionId":"2"},......}
The JSONKit, like all other JSON frameworks, does not play well with custom objects. To that end, you need to iterate through your object and put them into objects that the JSONKit can understand (NSArrays and NSDictionaries). Something like this:
NSMutableArray *jAnswers = [[[NSMutableArray alloc] init] autorelease];
for(Answer *answ in answers)
{
NSMutableDictionary *jAnswer = [[[NSMutableDictionary alloc] init] autorelease];
[jAnswer addObject: answ.answer forKey: #"answer"];
[jAnswer addObject: answ.questionId forKey: #"questionId"];
[jAnswers addObject: jAnswer];
}
NSString *jAnswersJSONFormat = [jAnswers JSONString];
would give you:
[{"answer": "1", "questionId": "1"}, {"answer": "5", "questionId": "2"}, ...]
JSONKit does seem to offer both a delegate-based and a block-based method for serializing unsupported object types. My guess, not having used the framework, is that you call one of those versions of the serialization methods and pass a delegate/selector pair or a block which returns a JSON-serializable object in place of an unsupported object type.
You'll want one of these category methods on NSArray:
- (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingDelegate:(id)delegate selector:(SEL)selector error:(NSError **)error;
- (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingBlock:(id(^)(id object))block error:(NSError **)error;

nested json with restkit on iphone

just trying to get used to restkit for iphone apps here at the moment and ive hit a wall. Im trying to get data from a nested json file.
[
{"person": {
"name": "joe",
"id": "1234",
"numbers":
[
{"value": "555-12125"},
{"value": "222-12125"}
]
}
}]
i set up the rkobjectmanager like so
RKObjectManager* manager = [RKObjectManager objectManagerWithBaseURL:#"http://localhost:3000"];
[manager loadObjectsAtResourcePath:#"/J.json?user_id=36995582&planner=insta-grammar" objectClass:[Person class] delegate:self] ;
[manager registerClass:[Person class] forElementNamed:#"person"];
[manager registerClass:[Numbers class] forElementNamed:#"numbers"];
then the person class and numbers class as follows
#import "Person.h"
#implementation Person
#synthesize _name,_id,_number;
+ (NSDictionary*)elementToPropertyMappings {
return [NSDictionary dictionaryWithKeysAndObjects:
#"name",#"name",
#"id",#"id",nil];
}
+ (NSDictionary*)elementToRelationshipMappings {
return [NSDictionary dictionaryWithKeysAndObjects:
#"numbers", #"numbers",
nil];
}
#end
#import "Numbers.h"
#implementation Numbers
#synthesize _number;
+ (NSDictionary*)elementToPropertyMappings {
return [NSDictionary dictionaryWithKeysAndObjects:
#"value",#"value",nil];
}
+ (NSString*)primaryKeyProperty {
return #"value";
}
+ (NSDictionary*)relationshipToPrimaryKeyPropertyMappings {
return [NSDictionary dictionaryWithObject:#"value" forKey:#"value"];
}
#end
but every time the _number remains empty after the didloadobjects function is called while the name and id variables fill up fine.
any ideas on this?.
ive tried the example on git but couldnt get it to work so any help would be appreciated.
thanks
g
What you need to do is to declare an NSArray *_numbers member variable in Person.h, make it a property like #property (nonatomic, retain) NSArray *_numbers and synthesize it in Person.m like #synthesize numbers = _numbers. Then you can get rid of whatever _number is, since you won't be storing a single number object, you will be storing an array of number objects.
Your Numbers class should instead just be Number, and you should synthesize your number variable like #synthesize number = _number;. So your Number.m should look like
#implementation Number
#synthesize number = _number;
+ (NSDictionary *)elementToPropertyMappings {
return [NSDictionary dictionaryWithKeysAndObjects:
#"value", #"number", nil];
}
Because your property is number, the mapping dictionary value is #"number", while your source JSON key should be #"value".
Then you can load the objects like (note we are using our Number class for the #"numbers" element):
RKObjectManager* manager = [RKObjectManager objectManagerWithBaseURL:#"http://localhost:3000"];
[manager registerClass:[Person class] forElementNamed:#"person"];
[manager registerClass:[Number class] forElementNamed:#"numbers"];
[manager loadObjectsAtResourcePath:#"/J.json?user_id=36995582&planner=insta-grammar" delegate:self];
For a full example see the Catalog Example int the RestKit github project
Just for anyone following up on this. Finally got this all working using the new OM2 that they have just released with restkit. very nice and easy to use change