Mapping With Restkit iphone - iphone

I am trying to map and store a response json data using restkit object mapping. unfortunately i cannot able to map a response data. when i view my database the datas are storing, but i get a crash with following message..
this class is not key value coding-compliant for the key
Output response
{
"users": [
{
"id": "123456",
"ne": "JohnSmith",
"el": "example#example.com",
"dob": "1985/02/04",
"profile": {
"id": "654321",
"ht": "170cm",
"wt": "70kg"
}
}
]
}
I am using mapping like this
RKManagedObjectMapping *userProfileMapping = [RKManagedObjectMapping mappingForClass:[GHSUser class] inManagedObjectStore:manager.objectStore];
[userProfileMapping mapKeyPath:#"id" toAttribute:#"userId"];
[userProfileMapping mapKeyPath:#"ne" toAttribute:#"name"];
[userProfileMapping mapKeyPath:#"el" toAttribute:#"email"];
[userProfileMapping mapKeyPath:#"dob" toAttribute:#"dob"];
RKManagedObjectMapping *standardProfileMapping = [RKManagedObjectMapping mappingForClass:[GHSProfile class] inManagedObjectStore:manager.objectStore];
[standardProfileMapping mapKeyPath:#"id" toAttribute:#"userId"];
[standardProfileMapping mapKeyPath:#"ht" toAttribute:#"height"];
[standardProfileMapping mapKeyPath:#"wt" toAttribute:#"weight"];
[manager.mappingProvider setMapping:standardProfileMapping forKeyPath:#"users.profile"];
//here in keypath(users.profile) i am getting crash,but profile details are inserting in db. when i change keypath to profile, i am not getting any crash but profile details are not inserting in db.
[userProfileMapping mapRelationship:#"users" withMapping:standardProfileMapping];
Error Message:
* Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<_NSObjectID_48_2 0x888a8d0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key profile.'

It is because your users parameter is an NSArray, not a NSDictionary. It doesn't know which users.profile to use.
You want to change the same line:
[manager.mappingProvider setMapping:standardProfileMapping forKeyPath:#"users.profile"];
to:
[manager.mappingProvider setMapping:userProfileMapping forKeyPath:#"users"];
and add this line to your userProfileMapping:
[userProfileMapping mapKeyPath: #"profile" toRelationship: #"profile" withMapping: standardProfileMapping]

Related

how to customize grails restful controller error response

How do we customize grails RestfulController error response? For example one of my restful controller returning following response by default on error while trying to save object.
{
"errors":
[
{
"object": "com.test.Task",
"field": "description",
"rejected-value": null,
"message": "Property [description] of class [class com.test.Task] cannot be null"
}
]
}
I would like to customize the response as bellow.
{
"errors" :
{
"message": "Property [description] of class [class com.test.Task] cannot be"
},
{
"message": "This is going to be any 2nd message"
},
.....
}
I found the solution
All you need is Register Custom Objects Marshallers on org.grails.datastore.mapping.validation.ValidationErrors class
def messageSource //inject messageSource
JSON.registerObjectMarshaller(ValidationErrors) { validationErrors ->
def errors = [] //add all errors into this list
validationErrors.target.errors.allErrors.each { error ->
errors.add(messageSource.getMessage(error, null)) //get messages from properties file.
}
//return map with errors list
return ["errors":errors]
}
Response will be:
{
"errors": [
"Property [description] of class [class com.test.Task] cannot be",
"This is going to be any 2nd message"
]
}
Use the Internationalization feature described here. Add the following to your resource bundle messages.properties.
task.description.nullable = your message
or
com.test.Task.description.nullable = your message

Facebook object API - duplicate objects created

I am creating objects through the open graph object API, and attaching these to published stories. Both the object and the story are created, and FB returns id's as if everything worked out just fine.
However, while submitting the object/story for review it turned out two objects are created (of different object types) even though I only make one HTTP POST request.
Background
Our app is using namespace 'mynamespace'
We have created a custom open graph object with name 'myobject'
We have created a custom open graph action with name 'myaction'
Request details:
1) First we create an object:
POST /me/objects/mynamespace:myobject HTTP/1.1\r\nConnection: close\r\nHost: graph.facebook.com\r\nContent-Length: LENGTH\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n
URI decoded http body:
access_token=TOKEN&object={"url":"http://url.com","title":"My title","image":"https://imageurl.com","description":"My description"}
Response:
"{\"id\":\"123456789\"}"
2) Then we create a story (with this object referenced):
POST /me/mynamespace:myaction HTTP/1.1\r\nConnection: close\r\nHost: graph.facebook.com\r\nContent-Length: LENGHT\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n
URI decoded http body:
access_token=TOKEN&myobject=123456789&fb:explicitly_shared=true&message=User generated message
Response:
"{\"id\":\"12121212121\"}"
Expected result
One object of type mynamespace:myobject should be created
One story of type mynamespace:myaction should be created
Actual result
One object of type mynamespace:myobject is created
One story of type mynamespace:myaction is created
One object of type Object is created (according to reviewer)
One action of type Post is created (according to reviewer)
Only one story turned up in the user feed and in the object browser, but the reviewer told us following:
Your action produces more than one published story when the user triggers the action. Users shouldn’t be surprised by multiple stories being published for a single in-app action. The action I took produced a "post" and a "myaction" story.
We had a look under (Open Graph -> Types) and it turned out that each time we make this request an object of type 'Object' and an action of type 'Post' is automatically created/defined! This must be what the reviewer complains about, but we haven't been able to figure out what we're doing wrong!
Any suggestions on how this can be solved is be very much appreciated.
Exact same issue when using the Open Graph API explorer
Turns out the exact same thing happens when creating an object through the Facebook Graph API explorer. When doing so the 'Object' object and the 'Post' action suddenly appears under Open Graph -> Types. Right now I see following reasons to this issue:
The object/action/story is set up incorrect in some way
The reviewer thought it was an issue when it actually wasn't
It's a FB bug
Object(s) created through the Graph API explorer
When creating an object through the Graph API explorer this is the resulting object:
{
"id": "4324324234234234",
"url": "http://url.com",
"type": "mynamespace:myaction",
"title": "My title",
"image": [
{
"url": "https://imageurl.com"
}
],
"description": "My description",
"updated_time": "2013-07-09T14:14:38+0000",
"created_time": "2013-07-09T14:14:38+0000",
"application": {
"id": "432423423423",
"name": "appname",
"url": "https://www.facebook.com/apps/appurl"
},
"is_scraped": false,
"post_action_id": "23423423423423423"
}
The 'post_action_id' seems weird, and when requesting that object I get:
{
"id": "423423423423",
"from": {
"name": "My name",
"id": "234234"
},
"start_time": "2013-07-09T14:14:38+0000",
"end_time": "2013-07-09T14:14:38+0000",
"publish_time": "2013-07-09T14:14:38+0000",
"application": {
"name": "appname",
"namespace": "mynamespace",
"id": "432423423423"
},
"data": {
"object": {
"id": "4324324234234234",
"url": "http://url.com",
"type": "mynamespace:myaction",
"title": "My title"
}
},
"type": "og.posts",
"likes": {
"count": 0,
"can_like": true,
"user_likes": false
},
"comments": {
"count": 0,
"can_comment": true,
"comment_order": "chronological"
}
}
The fact that the object already has a related og.posts object must be what the review think is the issue here. I still don't understand why this og.posts object automatically shows up as an open graph object though.
The issue here is that when the user clicks the "Peace" button on your site, two Open Graph actions are published and that's against our policy - one user action should not publish multiple stories. If you log in as your Open Graph Test User and check the Activity Log, you'll see the following two published actions with the same timestamp:
https://www.facebook.com/100006264788511/activity/1388570951361718
https://www.facebook.com/100006264788511/activity/1388570924695054
Are you sure your code is only making a single call to the Graph API when publishing the action?
I'm not sure how this would map to your POSTs, but I was dealing with the same issue on iOS and the problem is posting both the object and the action. If you set the object on the field other of the action (instead of the objectId after posting) only one Activity is created.
In my case, instead of doing:
NSMutableDictionary<FBOpenGraphObject> *object = [FBGraphObject openGraphObjectForPost];
object.provisionedForPost = YES;
object[#"title"] = #"Title";
object[#"type"] = #"video.other";
object[#"url"] = url;
[FBRequestConnection startForPostOpenGraphObject:object
completionHandler:^(FBRequestConnection *connection, id result, NSError *error)
{
if (!error && [result objectForKey:#"id"]) {
NSString* objectId = [result objectForKey:#"id"];
id<FBOpenGraphAction> action = (id<FBOpenGraphAction>)[FBGraphObject graphObject];
action[#"explicitly_shared"] = #"true";
action[#"other"] = objectId;
[FBRequestConnection startForPostWithGraphPath:#"me/myNamespace:post"
graphObject:action
completionHandler:^(FBRequestConnection *connection, id result, NSError *error)
{
// handle success and failures
}];
}
}];
I had to do:
NSMutableDictionary<FBOpenGraphObject> *object = [FBGraphObject openGraphObjectForPost];
object.provisionedForPost = YES;
object[#"title"] = #"Title";
object[#"type"] = #"video.other";
object[#"url"] = url;
id<FBOpenGraphAction> action = (id<FBOpenGraphAction>)[FBGraphObject graphObject];
action[#"explicitly_shared"] = #"true";
action[#"other"] = object;
[FBRequestConnection startForPostWithGraphPath:#"me/myNamespace:post"
graphObject:action
completionHandler:^(FBRequestConnection *connection, id result, NSError *error)
{
// handle success and failures
}];

JsonMappingException: Already had POJO for id

I have an error when trying to work with #JsonIdentityInfo jackson annotation. When I try to deserialize the object I get the following exception:
Could not read JSON: Already had POJO for id (java.lang.Integer) [1] (through reference chain: eu.cobiz.web.domain.Site["operators"]->eu.yavix.web.domain.Account["image"]->eu.cobiz.web.domain.Image["#Image"]);nested exception is com.fasterxml.jackson.databind.JsonMappingException: Already had POJO for id (java.lang.Integer) [1] (through reference chain: eu.yavix.web.domain.Site["operators"]->eu.cobiz.web.domain.Account["image"]->eu.cobiz.web.domain.Image["#Image"])
The JSON I am trying to deserialize looks like:
{
"#Site": 1,
"siteId": 1,
"name": "0",
"address": {
"#Address": 2,
"addressId": 4,
"number": "22"
},
"operators": [
{
"accountId": 1,
"email": "user982701361#yavix.eu",
"image": {
"#Image": 1,
"imageId": 1,
"uri": "http://icons.iconarchive.com/icons/deleket/purple-monsters/128/Alien-awake-icon.png"
}
},
{
"accountId": 2,
"email": "user174967957#yavix.eu",
"image": {
"#Image": 2,
"imageId": 2,
"uri": "http://icons.iconarchive.com/icons/deleket/purple-monsters/128/Alien-awake-icon.png"
}
}
]
}
My domain object is annotated with
#JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "#Image")
The problem arises on #Id annotation since if I remove the annotation the problem disappears (as I did for account) but on my understanding the new feature is useful for cyclic dependencies which is useful for me in other scenarios. There shouldn't be a conflict between the 2 images since they are different objects.
How can I solve this or what is the problem?
You should use scope parameter when annotating the ids. Then the de-serializer would make sure the id is unique within the scope.
From Annotation Type JsonIdentityInfo:
Scope is used to define applicability of an Object Id: all ids must be unique within their scope; where scope is defined as combination of this value and generator type.
e.g.
#JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class,property="#id", scope = Account.class)
To avoid id conflict try to use ObjectIdGenerators.PropertyGenerator.class or ObjectIdGenerators.UUIDGenerator.class instead of ObjectIdGenerators.IntSequenceGenerator.class

RestKit Object Mapping - One Entity, two mappings

After my last question was solved the JSON I'm receiving from the server changed to the following and I'm stuck handling the mapping to save the data with Core Data.
Entity
Key
- alias
- key
- keyType
- keyword
- unid
- until
JSON (from Server)
{
"documents": 1026,
"configuration":
{
...
},
"data":
[
{
"alias": "",
"key": "SALUTATION",
"keyType": "S",
"keyword": "Mr",
"unid": ""
},
...
{
"alias": "Automobile",
"key": "ACCOUNT_MARKET_SEGMENT",
"keyType": "A",
"keyword": "Automobile",
"unid": ""
}
],
"documentsFound": 770,
"maxCount": -1,
"since": "20120326200001",
"until": "20120326211309"
}
Now I want to map all the data from "data" plus the key "until" for the entity "Key" but can't find the right solution. My mapping so far to get the data looks like this and works well but misses the "until"-key, of course.
RKManagedObjectMapping* keyMapping = [RKManagedObjectMapping mappingForClass:[Key class]];
keyMapping.rootKeyPath = #"data";
[keyMapping mapKeyPath:#"key" toAttribute:#"key"];
[keyMapping mapKeyPath:#"keyword" toAttribute:#"keywordEN"];
[keyMapping mapKeyPath:#"alias" toAttribute:#"alias"];
keyMapping.setDefaultValueForMissingAttributes = YES;
Thanks for your ideas!
You are probably going to want to do two mappings. The first mapping will enclose the entire object and will have a relationship to the nested 'data' path.
RKObjectMapping *keyMapping = [RKObjectMapping mappingForClass:[Key class]];
[keyMapping mapAttributes:#"alias", #"key", nil];
[keyMapping mapKeyPath:#"keyword" toAttribute:#"keywordEN"];
RKObjectMapping *outerMapping = [RKObjectMapping mappingForClass:[Container class]];
[outerMapping mapKeyPath:#"data" toRelationship:#"keys" withMapping:keyMapping];
[outerMapping mapAttributes:#"since", #"until", "maxCount", "documentsFound", nil];
That will give you a new object with your metadata and then an array of the key objects on the keys attribute of your container. Rather than using the rootKeyPath, you can use the resourcePath based mapping registration on the 0.9.4 development branch (about to be released).

Reading a JSON string

I have a JSON String, in the format;
{
"name": "Alex",
"age": "12"
}
I know how to extract values from the above JSON. but at times, when there are no records in the database. i get a null value printed. (i undestand that this is not a valid JSON)
This null gets caught in the following if-condition.
SBJsonParser *parser = [SBJsonParser new];
NSDictionary *content = [pobjectWithString:[request responseString]];
if(!content){
NSLog(#" when its null it comes to this block");
return;
}
I need to read this value null and save it in a NSString. How can i do this ?
note: i have made use of ASIHTTPRequest to write the above code.
It's not clear what you're asking for. I think you want to detect when a null occurs (which you already seem to do with if(!content) ), then you want to create a string that either is empty, or has the word "null" in it. Why not:
if(!content) {
return #"null";
}
Of course, you could return whatever you wanted in the string.