Closed tomburns closed 10 years ago
you can overwrite -[NSManagedObject updateWithRawJSONDictionary:]
like
- (void)updateWithRawJSONDictionary:(NSDictionary *)d
{
[super updateWithRawJSONDictionary:d[@"user"]];
}
Thanks! When I overwrite that method, I don't see it getting called; if I set a breakpoint on the call to super
it's never hit. Is it possible that using mogenerator is causing trouble?
ive never worked with mogenerator, so i cant tell.
Here is the code I'm using to attempt to fetch the object (I am currently doing this in my AppDelegate for debug purposes):
NSURL *currentUserURL = [NSURL URLWithString:@"https://api.ravelry.com/current_user.json"];
[MNOCurrentUser fetchObjectFromURL:currentUserURL completionHandler:^(id fetchedObject, NSError *error) {
NSLog(@"%@",fetchedObject);
NSLog(@"%@",error);
}];
As far as I can tell, -updateWithRawJSONDictionary:
is not being called by this code, though by setting a breakpoint I can see +initialize
getting called on MNOCurrentUser
. I will continue attempting to get this working, but if you have any suggestions I would certainly appreciate it!
edit: Here's the complete console output:
2013-12-09 11:38:29.310 Merino[6045:1303] WARNING: JSON Object did not have an id ({
user = {
id = 1887075;
"photo_url" = "http://avatars.ravelry.com/tomburns/173709885/george-iawl_large.jpg";
"small_photo_url" = "http://avatars.ravelry.com/tomburns/173709885/george-iawl_small.jpg";
"tiny_photo_url" = "http://avatars.ravelry.com/tomburns/173709885/george-iawl_tiny.jpg";
username = tomburns;
};
})
2013-12-09 11:38:29.311 Merino[6045:70b] (null)
2013-12-09 11:38:29.311 Merino[6045:70b] Error Domain=SLRESTfulCoreDataErrorDomain Code=1 "API return an unexpected JSON object ({
user = {
id = 1887075;
"photo_url" = "http://avatars.ravelry.com/tomburns/173709885/george-iawl_large.jpg";
"small_photo_url" = "http://avatars.ravelry.com/tomburns/173709885/george-iawl_small.jpg";
"tiny_photo_url" = "http://avatars.ravelry.com/tomburns/173709885/george-iawl_tiny.jpg";
username = tomburns;
};
}) which cannot be converted into an NSManagedObject from URL https://api.ravelry.com/current_user.json." UserInfo=0xa25cfc0 {NSLocalizedDescription=API return an unexpected JSON object ({
user = {
id = 1887075;
"photo_url" = "http://avatars.ravelry.com/tomburns/173709885/george-iawl_large.jpg";
"small_photo_url" = "http://avatars.ravelry.com/tomburns/173709885/george-iawl_small.jpg";
"tiny_photo_url" = "http://avatars.ravelry.com/tomburns/173709885/george-iawl_tiny.jpg";
username = tomburns;
};
}) which cannot be converted into an NSManagedObject from URL https://api.ravelry.com/current_user.json.}
I was able to get this working by overwriting + (instancetype)updatedObjectWithRawJSONDictionary:inManagedObjectContext:
like so:
+ (instancetype)updatedObjectWithRawJSONDictionary:(NSDictionary *)rawDictionary inManagedObjectContext:(NSManagedObjectContext *)context
{
return [super updatedObjectWithRawJSONDictionary:rawDictionary[@"user"]
inManagedObjectContext:context];
}
Thanks for your help!
I also had to work around a similar issue with an API that always returns the JSON objects "wrapped" in a parent tag. Got this working fine, but now running up against the issue that array requests return a pluralised parent key. Eg., a request for a single user returns a dictionary with the representation inside the value of the "user" key, but a request for an array of users returns the JSON array as the value of the key "users".
I'm sure I can work around this somehow, but under the current implementation this isn't so obvious or easy. Perhaps, then, some sort of the provision for this is worth considering in a future version? If so, happy to help out.
@itsthejb do i understand this correctly? you have a route /users
which returns a json like
"users": [ {}, {}, {} ]
and you want to use fetchObjectsFromURL:completionHandler:
or fetchObjectsForRelationship:fromURL:completionHandler:
?
Hey Oliver,
More or less. Specifically, I want to perform a non-primary request that returns an array of course
objects, let's say it's something like -coursesBetweenDate:andDate
, and the JSON response returns a dictionary with the array as the value of the courses
key, so using those methods directly (as I want to) isn't currently possible. So it's:
"courses": [ {}, {}, {} ]
Coincidentally enough, for direct requests I have the same issue as @tomburns - requesting a course
by id (for example) returns the course object as the value of a parent course
property... Agree that this is redundant stuff, but I'm working with an existing API that's not likely to change so fundamentally right now.
"course": {}
Currently I'm actually using AFNetworking directly for my array requests, and more or less re-implementing a cut-down version of the fetch methods myself. This is actually fine enough for my needs (I think), but if you were interested in expanding the flexibility of the library then perhaps responses could provide some kind of unwrapping hook method. Perhaps, even, an optional block on the request itself? An API something like:
+ (void)fetchObjectsFromURL:(NSURL *)URL
responseFormatter:(id (^)(id JSONObject)) formatter
completionHandler:(void(^)(id fetchedObject, NSError *error))completionHandler
That way, when making a normal request you could do:
[self fetchObjectsFromURL:[NSURL URLWithString:@"some/url"]
responseFormatter:^id (id JSONObject)
{
return JSONObject[@"course"];
} completionHandler:^(id fetchedObject, NSError *error) {
...
}];
...and for my array example:
[self fetchObjectsFromURL:[NSURL URLWithString:@"some/url"]
responseFormatter:^id (id JSONObject)
{
return JSONObject[@"courses"];
} completionHandler:^(id fetchedObject, NSError *error) {
...
}];
Basically providing a hook to reformat the response in a way that the library itself expects.
What do you think? I'd be happy to do an implementation of this and a pull request this week if you'd like. I understand you want to keep the library itself as simple as possible, but can't hurt to make these kinds of customisations possible for users to adapt the library to their (idiosyncratic) APIs.
Thanks!
@itsthejb i decided to take a slightly different approach:
+[NSManagedObject registerJSONPrefix:]
and +[NSManagedObject registerPluralizedJSONPrefix:]
which you can used to register these json object prefixes. The json prefix will be used for fetching and posting/putting single objects and the pluralized json prefix for fetching multiple objects.SLRESTfulCoreDataBackgroundQueue
by @optional
- (void)registerResponseObjectTransformerForNextRequest:(SLRESTfulCoreDataBackgroundQueueObjectTransformer)responseObjectTransformer;
- (void)registerRequestObjectTransformerForNextRequest:(SLRESTfulCoreDataBackgroundQueueObjectTransformer)responseObjectTransformer;
which must handle these kinds of transformations in a thread safe manner and are totally opt-in.
AFRESTfulCoreDataBackgroundQueue
and SLRESTfulCoreData itself now support these request / response transformations depending on registered json prefixes.Feel free to give it a try, version 1.5.0 is currently pushed to https://github.com/Sparrow-Labs/Specs.
Hey Oliver,
This sounds great! I'll try these out right away and let you know if I have any feedback.
Thanks,
J
I'm hoping to use SLRESTfulCoreData with the API my app makes use of, but their JSON structure is a bit unorthodox. In the example below, I'm hoping to create a managed object of type MNOCurrentUser using the contents of the
user
hash which is returned:Is there a way to tell SLRESTfulCoreData to traverse the returned JSON and use the contents of
user
to populate the managed object?