Multiple KeyMappers per JSONModel - ios

JSONModel lets you convert a model object into a NSDictionary as following:
NSDictionary *dict = [myJSONModel toDictionary]
It includes all properties of the model (except optional). However, I also need to create multiple dictionaries having only some model fields required for a particular backend operation.
Some fields could be included in multiple dictionaries, so ideally, it would be awesome if I could do something like:
NSDictionary *dictOne = [myJSONModel dictionaryWithKeyMapper:myJSONMapperOne]
NSDictionary *dictTwo = [myJSONModel dictionaryWithKeyMapper:myJSONMapperTwo]
and it only returns the objects that have been mapped in that particular mapper.

I am sure there's nothing like this at present. The keymapper for every class is created only once and then is cached, so you can't changed it programatically. Plus you cannot ignore properties via the keymapper.
JSONModel is built like so that it supposes you always need to do the same transformations when you convert between JSON and your model, this way it can do the performance optimisations it does.
However "toDictionary" is not too complicated, you could try subclassing JSONModel and playing around with implementing a "toDictionaryWithFieldList" that takes in field names list and exports only those fields ... just an idea

Related

NSMutableDictionary contents inconsistent with output of allValues

So long story short, there's a discrepancy between the output of a NSMutableDictionary's contents and the result of calling allValues on the same object. Below is some debugger output after inspecting the object which demonstrates my problem: (made generic of course)
(lldb) po self.someDict.allKeys
<__NSArrayI 0xa5a2e00>(
<SomeObject: 0xa5a2dc0>,
<SomeObject: 0xa5a2de0>
)
(lldb) po self.someDict.allValues
<__NSArrayI 0xa895ca0>(
0.5,
0.5
)
(lldb) po self.someDict
{
"<SomeObject: 0xa5a2dc0>" = (null);
"<SomeObject: 0xa5a2de0>" = (null);
}
So as we can see, the actual output of the NSMutableDictionary contains null values for both its entries, but the contents of .allValues contains the proper data. These three outputs were taken at the same time in execution.
I'm not sure why this is happening, but I think it may have something to do with the fact that I'm encoding/decoding the object which this dictionary is a property of using CoreData. I believe I'm doing this properly:
[aCoder encodeObject:self.someDict forKey:#"someDict"];
and to decode
self.someDict = [aDecoder decodeObjectForKey:#"someDict"];
The weird thing is that if I inspect the dictionary before it ever gets encoded, it is still in the state described at the beginning of the post, so this is why I'm doubtful the CoreData actions are screwing with the contents.
As always, please don't hesitate to request additional information.
EDIT: The problem was as answered below. I was using a custom class which didn't cooperate with isEqual, so my solution was to change the storage and structure of my logic, which made using a Dictionary unnecessary.
I have not been able to duplicate the problem using NSString as keys and NSNumber as values. I suspect that your custom class does not properly implement hash and/or isEqual. Specifically, the results from those two methods must be consistent, meaning that if isEqual returns true, then the hash values for the two objects must be identical.
You also need to ensure that your class implements NSCopying properly and that a copy is equal to the original.
As a general rule, don't use custom objects for dictionary keys. Just use strings and be done with it.
As user3386109 points out, custom objects must properly implement the -hash and -isEqual methods in order to be used as dictionary keys, and even then, custom objects don't work correctly for dictionary keys for things like key/value coding.

Serializing a custom object into NSDictionary or NSArray to use NSJSONSerialization

I've been looking for a way to serialize custom objects with NSJSONSerialization avoiding the use of third-party libraries, and I couldn't find any example. Is there any way of "automatically" create an NSDictionary and NSArray from an object, without having to create it typing in code all the object's member names yourself one by one and setting manually the values? I found a related post, but it is pretty old, things may have now changed.
Thanks
You can use KVC to ask any object for dictionaryWithValuesForKeys: which will give you a dictionary representation of the object.
If you need to change the property / key names then you want to do some mapping and (depending on what you're using the JSON for) you may find RestKit useful.

Get NSManagedObject attribute validation regular expression

In my data model, some of the attributes have regular expressions used for data validation. There are places in my code that I would like to use those same regular expressions.
In the interest of keeping my common regular expressions in one place, I was hoping either to set these regexes in code or to retrieve them from the data model in code.
Is there a way to do this?
I want to access the Reg. Ex. property, shown below, in code.
From a NSEntityDescription you can get its attributes with the method attributesByName. Then you can use the NSPropertyDescription methods validationPredicates and setValidationPredicates:withValidationWarnings:. I assume that a predicate is created under the hood when you set the validation regex in your datamodel file...
I am not completely sure about this, but I think you can only set these values when you are creating your core data model, not once you have your core data stack set up. Is that what you want to do?
Absolutely. Everything you do in the model editor can be done or modified in code by manipulating your NSManagedObjectModel object.
Locate where the model is retrieved in your core data stack setup (maybe in your app delegate). Before returning the model, modify it in code, using constants you can #define in a central include file.
Read all about the object model's API here. More precisely, you set the model's entities after modifying an entity description, by changing the validationPredicates of one of its attributes.
I marked e1985's answer as accepted, since that's the answer that led me here. Here's the code I used to get the predicate. It's in a category for NSEntityDescription.
- (NSPredicate*)getValidationPredicateForAttribute:(NSString*)attributeName
{
NSAttributeDescription* emailAttribute = [self.attributesByName objectForKey:attributeName];
NSArray* validationPredicates = [emailAttribute validationPredicates];
if(validationPredicates.count > 0)
{
return [validationPredicates objectAtIndex:0];
}
return nil;
}

NSDictionary Vs. NSArray

I am reading on objective-c (a nerd ranch book), and I can't help thinking about this question: How do I decide which collection type, NSArray or NSDictionary (both with or w/o their mutable subclasses), to use when reading content from URL?
Let's say am reading JSON data from a PHP script (a scenario am dealing with), which to use? I know it is stated in many references that it depends on structure of data (i.e. JSON), but could a clear outline of the two structures be outlined?
Thank you all for helping :)
NSArray is basically just an ordered collection of objects, which can be accessed by index.
NSDictionary provides access to its objects by key(typically NSStrings, but could be any object type like hash table).
To generate an object graph from a JSON string loaded via a URL, you use NSJSONSerialization, which generates an Objective-C object structure. The resulting object depends on the JSON string. If the top-level element in your JSON is an array (starts with "["), you'll get an NSArray. If the top-level element is a JSON object (starts with "{"), you'll get an NSDictionary.
You want to use NSArray when ever you have a collection of the same type of objects, and NSDictionary when you have attributes on an object.
If you have, lets say a person object containing a name, a phone number and an email you would put it in a dictionary.
Doing so allows the order of the values to be random, and gives you a more reliable code.
If you want to have more then one person you can then put the person objects in an array.
Doing so allow you to iterate the user objects.
"withContentOfURL" or "withContentOfFile" requires the data in the URL or the file to be in a specific format as it is required by Cocoa. JSON is not that format. You can only use these methods if you wrote the data to the file or the URL yourself in the first place, with the same data. If you write an NSArray, you can read an NSArray. If you write an NSDictionary, you can read an NSDictionary. Everything else will fail.

NSDictionary with NSObjects as keys

I'm trying to create an NSDictionary that keeps track of calling objects for a function. I'd like to create a unique string for each object without knowing anything about it. My first thought is to use the memory address of the object's pointer, but I'm not sure how to do that.
Any thoughts? I need to use some sort of unique id from an NSObject as the keys in my dictionary.
If your application supports iOS6 only check the NSDictionaryOfVariableBindings macro.
The code would be something like :
// Create the dictionary
NSObject *firstObject = [NSString stringWithString:#"My first item"];
NSObject *secondObject = #"[#"an", #"array", #"of", #"strings"]";
NSDictionary *theDic = NSDictionaryOfVariableBindings(firstObject, secondObject);
// Access data
NSString *singleString = [theDic objectForKey:#"firstObject"];
NSArray *listOfStrings = [theDic objectForKey:#"secondObject"];
My suggestion is not to use a dictionary. If you were to place them into an array, you could think of it as a dictionary with automatically generated unique keys (the indexes). It's really exactly what you are describing. If for some reason you have to use a dictionary, my suggestion is to implement that same model I'm speaking of, but you would have to generate and maintain the keys.
While I agree that your solution sounds like it may not be the best approach, have you considered -hash in the NSObject protocol? All NSObjects should return one. Be forewarned that it's a hash, so there's a chance that two different objects could have the same hash.
You could also consider a category on NSObject that your collection implements. The category could generate a UUID to use as a key.

Resources