Objective-c SBJSONWriter convert array of dictionaries to JSON - objective-c

I'm having some trouble with SBJsonWriter at the moment.
I need to send a request that contains a json object of name/value pairs. e.g.
[{%22uid%22:1,%22version%22:1}]
I can't figure out how to do this in Obj-C with the SBJson Writer framework.
For each pair I have tried to construct a dictionary then add the dictionary to an array. This results in an array containing many dictionaries, each containing one name/value pair.
Any idea on how a fix for this or is it possible?
Thanks in advance

To produce an Objective-C structure equivalent to the above JSON you should do this:
NSArray* json = [NSArray arrayWithObject: [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt: 1], #"uid",
[NSNumber numberWithInt: 1], #"version",
nil]];

Check my answer to the '' SBJsonWriter Nested NSDictionary '' question. it illustrates how to properly use SBJsonWriter.
It includes error check and some pieces of advise about SBJsonWriter behaviour with NSDate, float, etc..
Excerpt:
NSDictionary* aNestedObject = [NSDictionary dictionaryWithObjectsAndKeys:
#"nestedStringValue", #"aStringInNestedObject",
[NSNumber numberWithInt:1], #"aNumberInNestedObject",
nil];
NSArray * aJSonArray = [[NSArray alloc] initWithObjects: #"arrayItem1", #"arrayItem2", #"arrayItem3", nil];
NSDictionary * jsonTestDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
#"stringValue", #"aString",
[NSNumber numberWithInt:1], #"aNumber",
[NSNumber numberWithFloat:1.2345f], #"aFloat",
[[NSDate date] description], #"aDate",
aNestedObject, #"nestedObject",
aJSonArray, #"aJSonArray",
nil];

Related

Using NSPredicate to filter based on multiple keys (NOT values for key)

I have the following NSArray containing NSDictionary(s):
NSArray *data = [[NSArray alloc] initWithObjects:
[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:1], #"bill", [NSNumber numberWithInt:2], #"joe", nil],
[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:3], #"bill", [NSNumber numberWithInt:4], #"joe", [NSNumber numberWithInt:5], #"jenny", nil],
[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:6], #"joe", [NSNumber numberWithInt:1], #"jenny", nil],
nil];
I am wanting to create a filtered NSArray that only contains objects where the NSDictionary matches multiple 'keys' using NSPredicate.
For example:
filter the array to only contain the NSDictionary objects that have keys "bill" and "joe" [desired result: new NSArray would contain the first two NSDictionary objects]
filter the array to only contain the NSDictionary objects that have keys "joe" and "jenny" [desired result: new NSArray would contain the last two NSDictionary objects]
Can anyone please explain the format of the NSPredicate to achieve this?
Edit:
I can achieve a similar outcome to desired NSPredicate using:
NSMutableArray *filteredSet = [[NSMutableArray alloc] initWithCapacity:[data count]];
NSString *keySearch1 = [NSString stringWithString:#"bill"];
NSString *keySearch2 = [NSString stringWithString:#"joe"];
for (NSDictionary *currentDict in data){
// objectForKey will return nil if a key doesn't exists.
if ([currentDict objectForKey:keySearch1] && [currentDict objectForKey:keySearch2]){
[filteredSet addObject:currentDict];
}
}
NSLog(#"filteredSet: %#", filteredSet);
I'm imagining NSPredicate would be more elegant if one exists?
they only way I know is to combine two conditions like "'value1' IN list AND 'value2' IN list"
self.#allKeys should return all the keys of the dictionary (self is each dictionary in your array). If you don't write it with the prefix # then the dictionary will just look for a key that is "allKeys" instead of the method "- (NSArray*) allKeys"
The code:
NSArray* billAndJoe = [data filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"%# IN self.#allKeys AND %# IN self.#allKeys" , #"bill",#"joe" ]];
NSArray* joeAndJenny = [data filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"%# IN self.#allKeys AND %# IN self.#allKeys" , #"joe",#"jenny" ]]
Since a dictionary just returns nil if you ask for a value of a non-existing key, it is enough to specify that the value should be non-nil. A format like the following should cover your first case:
[NSPredicate predicateWithFormat: #"%K != nil AND %K != nil", #"bill", #"joe"]
The second case, with "joe" and "jenny" follows a similar pattern, of course.

Which type I should use to save many objects with same key? (iOS)

Which type I should use to save many objects with same key?
I should post data to server where one of parameter is suggestedTo and it contains userId.
This parameters should be more then one. So I'm confused which data type I should use to save them.
For example array or dictionary should looks like
{
#"suggestedTo" = 111,
#"suggestedTo" = 222,
#"suggestedTo" = 333,
etc.
}
This is typically handled with a dictionary of sets (or arrays if the data is ordered). So in this case, you'd have something like:
NSSet *suggestedTo = [NSSet setWithObjects:[NSNumber numberWithInt:111],
[NSNumber numberWithInt:222],
[NSNumber numberWithInt:333], nil];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:suggestedTo,
#"suggestedTo", nil];
You could use a dictionary of arrays
NSArray *suggestedTos = [[NSArray alloc] initWithObjects:
[NSNumber numberWithInt:111],
[NSNumber numberWithInt:222],
[NSNumber numberWithInt:333], nil];
NSDictionary *myDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:
suggestedTos, #"suggestedTo", nil];

How can I access this variable Globally in Objective C?

Here is the code im having issues with:
if(DriveInfoDict) {
NSLog(#"%#", DriveInfoDict);
//PrevSpeedsDict = [DriveInfoDict objectForKey: #"speed"];
//NSLog(#"Previous Speed Dict:%#", PrevSpeedsDict);
}
DriveInfoDict = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithDouble: CurrentLatitude], #"Lat",
[NSNumber numberWithDouble: CurrentLongitude], #"Long",
[NSNumber numberWithDouble:speedMPH], #"speed",
nil];
Here, I would like to set DriveInfoDict, so that the next time the function runs it will have the previous value. I have stripped the operators to simplify my problem.
The error I am getting is : EXC-BAD-ACCESS
I am new to Obj-C and I do not know how to make this object accessible here. Some code with explanation as to if it goes in the H or M file would be very helpful.
You need to retain the dictionary or use alloc/init (which returns a retained dictionary. So either:
DriveInfoDict = [[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithDouble: CurrentLatitude], #"Lat",
[NSNumber numberWithDouble: CurrentLongitude], #"Long",
[NSNumber numberWithDouble:speedMPH], #"speed",
nil] retain];
or:
DriveInfoDict = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithDouble: CurrentLatitude], #"Lat",
[NSNumber numberWithDouble: CurrentLongitude], #"Long",
[NSNumber numberWithDouble:speedMPH], #"speed",
nil];
If you replace the content of DriveInfoDict (that is: assign a new dictionary) don't forget to first release it.

From array of dictionaries, make array containing values of one key

I have an array of dictionaries. I would like to extract an array with all the elements of one particular key of the dictionaries in the original array. Can this be done without enumeration?
Yes, use the NSArray -valueForKey: method.
NSArray *extracted = [sourceArray valueForKey:#"a key"];
Yes, just use Key-Value Coding to ask for the values of the key:
NSArray* names = [NSArray arrayWithObjects:
[NSDictionary dictionaryWithObjectsAndKeys:
#"Joe",#"firstname",
#"Bloggs",#"surname",
nil],
[NSDictionary dictionaryWithObjectsAndKeys:
#"Simon",#"firstname",
#"Templar",#"surname",
nil],
[NSDictionary dictionaryWithObjectsAndKeys:
#"Amelia",#"firstname",
#"Pond",#"surname",
nil],
nil];
//use KVC to get the names
NSArray* firstNames = [names valueForKey:#"firstname"];
NSLog(#"first names: %#",firstNames);

NSMutable Dictionary adding objects

Is there a more efficient way to add objects to an NSMutable Dictionary than simple iteration?
Example:
// Create the dictionary
NSMutableDictionary *myMutableDictionary = [NSMutableDictionary dictionary];
// Add the entries
[myMutableDictionary setObject:#"Stack Overflow" forKey:#"http://stackoverflow.com"];
[myMutableDictionary setObject:#"SlashDotOrg" forKey:#"http://www.slashdot.org"];
[myMutableDictionary setObject:#"Oracle" forKey:#"http://www.oracle.com"];
Just curious, I'm sure that this is the way it has to be done.
NSDictionary *entry = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithDouble:acceleration.x], #"x",
[NSNumber numberWithDouble:acceleration.y], #"y",
[NSNumber numberWithDouble:acceleration.z], #"z",
[NSDate date], #"date",
nil];
If you have all the objects and keys beforehand you can initialize it using NSDictionary's:
dictionaryWithObjects:forKeys:
Of course this will give you immutable dictionary not mutable. It depends on your usage which one you need, you can get a mutable copy from NSDictionary but it seems easier just to use your original code in that case:
NSDictionary * dic = [NSDictionary dictionaryWith....];
NSMutableDictionary * md = [dic mutableCopy];
... use md ...
[md release];
Allow me to add some information to people that are starting.
It is possible to create a NSDictionary with a more friendly syntax with objective-c literals:
NSDictionary *dict = #{
key1 : object1,
key2 : object2,
key3 : object3 };
NSMutableDictionary *example = [[NSMutableDictionary alloc]initWithObjectsAndKeys:#5,#"burgers",#3, #"milkShakes",nil];
The objects come before the keys.