TestsTested | ✗ |
LangLanguage | Obj-CObjective C |
License | MIT |
ReleasedLast Release | Dec 2014 |
Maintained by Unclaimed.
JAGPropertyConverter is a library to allow easy serialization/deserialization to/from JSON or PropertyList formats.
JAGPropertyConverter allows you to convert a JSON dictionary such as
{
"userID" : 1234,
"name" : "Jane Smith",
"likes" : ["swimming", "movies", "tennis"],
"invitedBy" : {
"userID" : 9876,
"name" : "Bob Willis"
},
"friends" : [
{ "userID" : 8873, "name" : "Jodi Fischer" },
{ "userID" : 9876, "name" : "Bob Willis" }
]
}
to/from Objective-C "model" classes such as:
@interface User : NSObject
@property (assign) int userID;
@property (copy) NSString *name;
@property (strong) NSArray *likes;
@property (strong) User *invitedBy;
@property (strong) NSSet *friends;
@end
It does this by using the objc runtime library to discover which properties are defined on an object, and then using Key-Value coding to set/retrieve the values.
It will convert recursively, so a model's dictionary of models with array properties of further models will be handled correctly.
There are three "outputTypes" that the converter supports when converting from a model to an NSDictionary: Full, PropertyList, and JSON.
Converterting from a Model to an NSDictionary is relatively straightforward, using the property name as a key and the property value as a value. Converting from an NSDictionary to a model requires an important first step of recognizing what Model class the NSDictionary represents. JAGPropertyConverter has an "identifyDict" block property that checks any NSDictionary value, and if it returns a Class, the converter attempts to convert the NSDictionary into that class. If identifyDict returns nil, the converter leaves the NSDictionary unchanged.
To determine which NSObject subclasses are considered "Models" (i.e., which it should convert), JAGPropertyConverter relies on its classesToConvert property. Objects which are subclasses of a Class in classesToConvert are converted.
By default, weak/assign object pointers are not converted (but assign properties for scalars are). This is because weak references often indicate a retain loop (eg, between an object and its delegate), which would lead to cycle in the object graph and thence an infinite loop in the conversion. This property can be controlled by the "shouldConvertWeakProperties" in JAGPropertyConverter.
NSURL properties are not technically valid for JSON or ProperyLists, so JAGPropertyConverter serializes/deserializes them using the string of the absolute path.
NSDate properties are not valid for JSON, and different use cases will call for different serialization methods. We allow for this by the convertToDate and convertFromDate block properties. They are called when converting to/from NSDate properties with JSON output type.
NSObject itself has some properties. JAGPropertyFinder ignores these. If there is need in the future, JAGPropertyFinder could take a setting determining whether it ignores or finds those properties.
JAGPropertyConverter converts arrays to sets and vice-versa, as needed.
//Serialization
MyModel *model = [MyModel populatedModel];
JAGPropertyConverter *converter = [[JAGPropertyConverter alloc] initWithOutputType:kJAGJSONOutput];
converter.classesToConvert = [NSSet setWithObject:[MyModel class]];
NSDictionary *jsonDictionary = [converter convertToDictionary:model];
//Deserialization
NSDictionary *jsonDictionary = [NSDictionary dictionaryWithContentsOfFile:@"/path/to/model.json"];
JAGPropertyConverter *converter = [[JAGPropertyConverter alloc] init];
converter.identifyDict = ^(NSDictionary *dict) {
if ([dict valueForKey:@"userID"]) {
return [User class];
} else if ([dict valueForKey:@"primaryKey"]) {
return [MyModel class];
}
return nil;
}
MyModel *model = [converter composeModelFromObject:jsonDictionary];
The converter can also handle NSArray, NSSet, and NSDictionary inputs as well.
Since JAGPropertyConverter uses Key-Value coding to get/set values, it doesn't respect custom getters and setters with non-standard names. JAGProperty has this ability, so we could in theory support this. Two things have dissuaded us so far. The first is that ARC produces warnings, since you are invoking an unknown (to it) selector to get/set properties, so it can't ensure memory management is handled correctly. The second is that Key-Value coding handles scalars decently well, which would take a little more work to do when directly using the properties getters and setters.
While Key-Value coding handles struct (and similar) scalars decently well, we have not yet enabled JAGPropertyConverter to parse them into a JSON-value format.
JAGPropertyConverter requires iOS 4.0 or higher, and uses ARC. In theory it should also work with OS X 10.6 or higher, but so far it has only been tested for iOS development.
JAGPropertyConverter was created by James Gill in the development of SpotNote. The intial code for JAGProperty came from Mike Ash's RTProperty class, in his excellent runtime libraries. The documentation was generated by appledoc, and the tag versioning follows Semantic Versioning.
JAGPropertyConverter is available under the MIT license. See the LICENSE file for more info.