Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

nested (MTLModel) classes #46

Closed
matzew opened this Issue Nov 16, 2012 · 16 comments

Comments

Projects
None yet
3 participants

matzew commented Nov 16, 2012

Having the following object model:

A simple employee class:

@interface MWEmployee : MTLModel

@property (nonatomic, copy) NSString* name;
@property (nonatomic, copy) NSArray* tasks;

@end

And employees can have tasks:

@interface MWTask : MTLModel

@property (nonatomic, copy) NSString* title;
@property (nonatomic, copy) NSString* desc;

@end

Now let's build a simple object graph:

MWTask* task = [[MWTask alloc] init];
task.title = @"Some task";
task.desc = @"lot's of workz";

MWEmployee* emp = [[MWEmployee alloc] init];
emp.name = @"Mr. X";
emp.tasks = [NSArray arrayWithObject:task];

Now let's try to get some JSON:

NSData* encodedData = [NSJSONSerialization
    dataWithJSONObject:[emp externalRepresentation] // using the given NSDictionary
    options:NSJSONWritingPrettyPrinted error:nil];
NSString* jsonString = [[NSString alloc] initWithData:encodedData encoding:NSUTF8StringEncoding];

But I am getting nothing back (as JSON), the NSJSONSerialization fails and says Invalid type in JSON write (MWTask)

Are nested (MTLModel) classes not supported ?

Owner

jspahrsummers commented Nov 16, 2012

They are, but you must explicitly specify how they get transformed to and from JSON, like by using mtl_externalRepresentationArrayTransformerWithModelClass:.

Owner

jspahrsummers commented Nov 16, 2012

For example, in your MWEmployee class, you'll want to do something like the following:

+ (NSValueTransformer *)tasksTransformer {
    return [NSValueTransformer mtl_externalRepresentationArrayTransformerWithModelClass:MWTask.class];
}

matzew commented Nov 18, 2012

@jspahrsummers thanks for the quick response!

@matzew matzew closed this Nov 18, 2012

matzew commented Nov 18, 2012

Hrm, did this in my MWEmployee.m file:

@implementation MWEmployee
- (NSValueTransformer *)tasksTransformer {
    return [NSValueTransformer mtl_externalRepresentationArrayTransformerWithModelClass:MWTask.class];
}
@end

still getting the same error

@matzew matzew reopened this Nov 18, 2012

Owner

jspahrsummers commented Nov 18, 2012

Sorry, that should've been a class method. I've updated my comment to reflect as much.

matzew commented Nov 19, 2012

ah - thx.

For reading from JSON this would be the preferred choice, right ?

    NSData* data = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
    NSDictionary* parsedObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];


    MWEmployee* myParsedEmp = [[MWEmployee alloc] initWithExternalRepresentation:parsedObject];

@matzew matzew closed this Nov 19, 2012

Owner

jspahrsummers commented Nov 19, 2012

Yep, that'll do it, though you may want to verify at runtime that parsedObject is actually a dictionary before passing it on to -initWithExternalRepresentation: (since it'd also be valid JSON for it to be an array).

I knew there was a simple answer I just didn't connect 2 + 2. Could this make README status? Is it mitigated by a planned feature?

Owner

jspahrsummers commented Jan 9, 2013

I'm not sure what else would go into the README. We already have an example demonstrating this stuff.

Nested models specifically like your + tasksTransformer snippet.

I had found that NSValueTransformer category reading the headers. But it didn't click what it's intended for. Or why it wasn't another named transformer (PR?) like URLs and booleans. I was also wondering whether MTLModel would provide mtl_externalRepresentationTransformerWithModelClass: reflectively hence the mtl_ prefix.

Owner

jspahrsummers commented Jan 13, 2013

@dnalot Fair enough. I'll open this as a reminder to add something like that.

Pull requests always welcome, too. :)

@jspahrsummers jspahrsummers reopened this Jan 13, 2013

I could send a PR migrating those methods to named transformers (unless I haven't noticed yet why they weren't originally) but the documentation seems challenging because its example (and neatly so) is domain specific to GH.

Owner

jspahrsummers commented Jan 15, 2013

@dnalot Named transformers can't be used because they require a specific MTLModel subclass to transform to and from.

I feel dense. Would a user-redefineable mtl_modelClass key and value (by default but not necessarily NSStringFromClass()) to the external representation for inferring Mantle transformers be overengineered (or under if it encourages brittle representations)?

Owner

jspahrsummers commented Jan 16, 2013

Yeah, that would be too brittle, and it assumes that the external representation can support arbitrary keys, which isn't always the case (e.g., sending JSON to the server).

That makes sense.

@jspahrsummers jspahrsummers was assigned Mar 1, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment