Xcode how to NSLog a JSON - objective-c

Is there any way to get NSLog to print out an entire JSON file. I am currently saying
NSString *deviceInfo = [NSString stringWithFormat:#"%# %#",
[[UIDevice currentDevice]model], [[UIDevice currentDevice]systemVersion]];
NSDictionary *json = [deviceInfo JSONValue];
NSLog(#"json file = %#", json);
And it is printing out "json file = (null)"
Thanks
Clinton

I think you’re misunderstanding what JSON is for. The string you’re passing to -JSONValue isn’t a valid JSON string, so it’s returning nil. You might as well just construct the dictionary yourself:
UIDevice *device = [UIDevice currentDevice];
NSDictionary *deviceInfo = [NSDictionary dictionaryWithObjectsAndKeys:[device model], #"deviceModel", [device systemVersion], #"deviceSystemVersion", nil];
Then if you want the JSON string representation of the object (for sending to your server, for instance):
NSString *jsonDeviceInfo = [deviceInfo JSONRepresentation];

Are you sure that your code works correctly? Your NSDictionary seems to be nil ...
Could you please post the implementation of JSONValue?
If an object doesn't print as expected you can always override the -(NSString *) description method through an extension and it will print how you've specified :)

Related

NSDictionary writeToFile fails while objects are valid, permission is 0k

Why NSDictionary cannot be written?? I have checked the content of the dictionary: all the instances are of NSString and NSNumber. I checked permissions: a text file with the same name at the same path is written well. Of course, my dictionary is not empty.
NSString *file = ...
NSDictionary *dict = ...
// check dictionary keys
BOOL wrong = NO;
for (id num in [dict allKeys]) {
if (![num isKindOfClass:[NSNumber class]]) {
wrong = YES;
break;
}
}
if (wrong) {
NSLog(#"First");
}
// check dictionary values
wrong = NO;
for (id num in [dict allValues]) {
if (![num isKindOfClass:[NSString class]]) {
wrong = YES;
break;
}
}
if (wrong) {
NSLog(#"Second");
}
if (![dict writeToFile:file atomically:YES]) {
// 0k, let's try to create a text file
NSLog(#"Names writing error!");
[#"Something here... .. ." writeToFile:file atomically:YES encoding:NSUTF8StringEncoding error:nil];
}
Output: "Names writing error!"
Text file is created successfully.
Writing out a dictionary creates a property list, and according to the documentation all keys in a property list must be strings.
... and although NSDictionary and CFDictionary objects allow their keys to
be objects of any type, if the keys are not string objects, the
collections are not property-list objects.
NSNumber objects as keys are not supported.
As #vadian points out, you cannot write plist with numeric keys. But you can use NSKeyedArchiver:
NSURL *documents = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:false error:nil];
NSURL *fileURL = [documents URLByAppendingPathComponent:#"test.plist"];
// this will not work
NSDictionary *dictionary = #{#1: #"foo", #2: #"bar"};
BOOL success = [dictionary writeToFile:fileURL.path atomically:true];
NSLog(#"plist %#", success ? #"success" : #"failure");
// this will
fileURL = [documents URLByAppendingPathComponent:#"test.bplist"];
success = [NSKeyedArchiver archiveRootObject:dictionary toFile:fileURL.path];
NSLog(#"archive %#", success ? #"success" : #"failure");
And you can read it back with NSKeyedUnarchiver:
// to read it back
NSDictionary *dictionary2 = [NSKeyedUnarchiver unarchiveObjectWithFile:fileURL.path];
NSLog(#"dictionary2 = %#", dictionary2);
Note, you can do this with any class that conforms (and properly implements) NSCoding. Fortunately, NSDictionary conforms already. You have to make sure that any objects inside the dictionary, also conform (both NSString and NSNumber do). If you had a custom object in your dictionary, you'd have to make it properly conform yourself.
This is all described in the Archives and Serializations Programming Guide.

Programmatically delete parts of NSString

I have an iOS app which connects to a server via OAuth 2.0. I get returned an access token in this form:
{accessToken="521515.ab6dc96.51dca3d53c4236d2d4f4460b151bc58d6ec91e14"}
And I store that in a NSString. The problem I am having is that I ONLY need the part which is in the quotation marks. How can I extract that?
UPDATE
Here us my code:
GTMOAuth2Authentication *auth_instagram;
auth_instagram = [GTMOAuth2ViewControllerTouch authForGoogleFromKeychainForName:#"Instagram" clientID:kMyClientID_instagram clientSecret:kMyClientSecret_instagram];
NSLog(#"%#", auth_instagram);
Printed in the Xcode console is:
GTMOAuth2Authentication 0xb2c0a80: {accessToken="541019.ab6dc96.51dc0d264d2d4f60b151bc8d6ec91e14"}
If I read the class definition at http://code.google.com/p/gtm-oauth2/source/browse/trunk/Source/GTMOAuth2Authentication.h correctly, GTMOAuth2Authentication has a
#property (retain) NSString *accessToken;
so that you can just do
NSString *token = auth_instagram.accessToken;
to get the token as a string.
Remark: Your output
{accessToken="521515.ab6dc96.51dca3d53c4236d2d4f4460b151bc58d6ec91e14"}
is the result of calling the description method of GTMOAuth2Authentication.
This is not JSON. JSON would look like
{ "accessToken" : "521515.ab6dc96.51dca3d53c4236d2d4f4460b151bc58d6ec91e14" }
The right way would be to parse the whole string using the correct format/parser, in this case probably NSJSONSerialization and extract the value from the accessToken element.
NSDictionary *parsedData = [JSONObjectWithData:[string dataUsingEncoding:NSUTF8StringEncoding] options:0 error:NULL];
NSString *value = parsedData[#"accessToken"];
NSArray* components = [accessStr componentsSeparatedByString: "\""];
NSString* requiredStr = [components objectAtIndex: 1];
NSDictionary *dic =[NSJSONSerialization JSONObjectWithData: [YourString dataUsingEncoding:NSUTF8StringEncoding] options: NSJSONReadingMutableContainers error: &e];
//yourstring is the string in which u store and &e is just an NSError u can create urself like NSError *e;
NSString access_Token=[dic objectForKey:#"accessToken"];
What you got there is valid JASON. Try the following:
NSDictionary *loginInfo = [NSJSONSerialization JSONObjectWithData:[#"{accessToken=\"521515.ab6dc96.51dca3d53c4236d2d4f4460b151bc58d6ec91e14\"}" dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:nil];
NSString *aToken = [loginInfon objectForKey:#"accessToken"];

How to convert json string to nsdictionary on json parser framework on objective c

I am trying to convert raw json string to NSDictionary. but on NSDictionary i got different order of objects as on json string but i need exactly same order in NSDictionary as on json string. following is code i have used to convert json string
SBJSON *objJson = [[SBJSON alloc] init];
NSError *error = nil;
NSDictionary *dictResults = [objJson objectWithString:jsonString error:&error];
From NSDictionary's class reference:
The order of the keys is not defined.
So, basically you can't do this when using a standard NSDictionary.
However, this may be a good reason for subclassing NSDictionary itself. See this question about the details.
NSDictionary is an associative array and does not preserve order of it's elements. If you know all your keys, then you can create some array, that holds all keys in correct order (you can also pass it with your JSON as an additional parameter). Example:
NSArray* ordered_keys = [NSArray arrayWithObjects: #"key1", #"key2", #"key3", .., nil];
for(NSString* key is ordered_keys) {
NSLog(#"%#", [json_dict valueForKey: key]);
}
//parse out the json data
NSError* error;
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:responseData //1
options:kNilOptions
error:&error];
NSArray* latestLoans = [json objectForKey:#"loans"]; //2
NSLog(#"loans: %#", latestLoans); //3
Source: Follow this link http://www.raywenderlich.com/5492/working-with-json-in-ios-5
Good tutorial but works only on iOS5

How to compare strings in objective-c?

I am having problems in comparing two string objects in objective-c. Here is my situation:
I have two NSString objects in my view controller as follow shown in my code below, in my .h file:
#property(nonatomic,retain) NSString *detailFacility;
in my .m file in viewDidLoad function:
- (void)viewDidLoad
{
NSData *facilityZoneURL = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"some URL..."]]];
NSError *error;
NSDictionary *facilityZoneDict = [NSJSONSerialization JSONObjectWithData:facilityZoneURL options:kNilOptions error:&error];
NSArray *facilityZoneData = [facilityZoneDict objectForKey:#"Data"];
if (![facilityZoneData isKindOfClass:[NSArray class]]) {
//JSON does not returned the Dictionary;
}
facilityZoneArray = [[NSMutableArray alloc] init];
NSLog(#"%#",detailFacility);
for (NSDictionary *item in facilityZoneData) {
NSString *zoneFacilityID = [NSString stringWithFormat:#"%#",[item objectForKey:#"FacilityId"]];
NSLog(#"Facility ID: %# --- Zone ID: %#",detailFacility,zoneFacilityID);
NSLog(#"%#",[zoneFacilityID isEqualToString:detailFacility]? #"YES" : #"NO");
if ([zoneFacilityID isEqualToString:detailFacility]) {
NSLog(#"object added");
}
}
But the problem is it is not comparing the strings as it is surely matches as some position.
here is my NSLOG situation:
2012-04-02 12:12:42.998 CarbonIndex[11078:207] Facility ID: 1056 --- Zone ID: 1056
2012-04-02 12:12:42.999 CarbonIndex[11078:207] NO
As you can see that both the string are accurately matched, but the if-condition does not execute, Tell me what I am missing in it.
It's likely an encoding issue. Try using something like this and see if it helps:
NSLog(#"%#",[zoneFacilityID compare:detailFacility]==NSOrderedSame? #"YES" : #"NO");
Compare works better with different encoding normalizations. See details here: http://weblog.bignerdranch.com/?p=334
More likely than not, one of your strings is not a string. It is an NSNumber and, thus, trying to do a string comparison is failing.
Try changing your logging to verify this:
NSLog(#"Facility ID: %# --- Zone ID: %#",[detailFacility class],
[zoneFacilityID class]);
If that is the case, then you'll likely want to change whatever code that is currently expected to store an NSString to storing an NSNumber, then use isEqual: on the number instances (as that will be faster and more straightforward than number->string conversions everywhere).

ASIHttpRequest - how to convert NSDictionary of params to url-encoded query param string?

What is the preferred way to make a GET request with ASIHttpRequest using query params provided as an NSDictionary.
How do I get
from NSDictionary *params
to ?param1=value1&param2=value2 (percent-encoded)
Obviously I can construct the query part of the URL manually but it seems like there is probably a better way.
Thanks!
You must pass the query string as part of the URL. From the ASIHTTPRequest interface on GitHub:
// The url for this operation, should include GET params in the query string where appropriate
NSURL *url;
If you don't want to roll your own dictionary-to-query-string method, take a look at the GTMNSDictionary+URLArguments category in Google Toolbox for Mac (.h, .m). It adds a method, gtm_httpArgumentString, to NSDictionary that should be what you're after.
I am not using ASIHTTPRequest, but I have a similar need for a URLRequest I make. Here is what I am doing:
- (NSString *) createParamString
{
NSDictionary *params = // build up the param dictionary
NSString *result = #"";
id key;
NSEnumerator *enumerator = [params keyEnumerator];
while (key = [enumerator nextObject]) {
result = [result stringByAppendingFormat:#"%#=%#&", key, [params objectForKey:key]];
}
result = [result substringToIndex:[result length] - 2];
return [result stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
}
Not sure if it's perfect for all situations, but it's working well enough for me