creating JSON String - objective-c

I have task that involves creating the right design for the JSON string before I can get a response from the webservice. The JSON string has to look like this:
{"nid":"","vocab":"", "inturl":"testoverview", "mail":"", "md5pw":""}
and my JSON string looks like this:
"nid:",
"vocab:",
"inturl:testoverview",
"mail:",
"md5pw:"
as you can see it's not built the same way, I'm not using braces, or separating the strings the right way. And I don't know how to do this.
my code for this is here:
NSString *nid = #"nid:";
NSString *vocab = #"vocab:";
NSString *inturl = #"inturl:testoverview";
NSString *mail = #"mail:";
NSString *md5pw = #"md5pw:";
NSArray *jsonArray = [NSArray arrayWithObjects:nid, vocab, inturl, mail, md5pw, nil];
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonArray options:NSJSONWritingPrettyPrinted error:&error];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
FSProductTestHandler *handler = [[FSProductTestHandler alloc] init];
if (!jsonData) {
NSLog(#"Got an error; %#", error);
} else if(jsonData) {
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSString *url = #"http://www.taenk.dk/services/mobile";
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLCacheStorageAllowed timeoutInterval:30.0];
[request setValue:jsonString forHTTPHeaderField:#"X-FBR-App"];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
Can anyone help me with this issue?

You are feeding an array to the serialisation which means you'll get a JSON array as output i.e soemthing like:
[ "foo", "bar", "baz"]
(note the brackets [ ...] instead of braces { ... })
You need to build an NSDictionary and for your particular example, the quickest way is like this:
NSDictionary* dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
#"", #"nid",
#"", #"vocab",
#"testoverview", #"inturl",
#"", #"md5pw",
#"", #"mail",
nil];
Feed that into NSJSONSerialization and you'll get what you want.

Related

Error 400 and 415 when exchanging code for access_token

I am writing an application to authorise itself into Spotify. I used the node app.js example to get things working and an now re-writing natively into Objective C. I have extracted the authorisation code via a callback function
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"https://accounts.spotify.com/api/token"]];
request.HTTPMethod = #"POST";
// put in the header fields
NSString *headerString = [NSString stringWithFormat:#"%#:%#",clientID,clientSecret];
NSData *nsdata = [headerString dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64Encoded = [nsdata base64EncodedStringWithOptions:0];
base64Encoded = [ NSString stringWithFormat:#"Basic %#", base64Encoded];
[request setValue:base64Encoded forHTTPHeaderField:#"Authorization"];
NSLog(#"request.header %#", request.allHTTPHeaderFields.description);
// put in the body form
NSString * stringData = [NSString stringWithFormat:#"grant_type:%#, code:%#, redirect_uri:\"%#\"", #"authorization_code",authorisationCode,redirectUri];
NSData * requestBodyData = [stringData dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPBody = requestBodyData;
NSLog(#"request.body %#", [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding]);
I then post this request and get
{"error":"server_error","error_description":"Unexpected status: 415"}
returned.
I have found a variety of questions on this topic revolving around the Content-Type needing to be application/x-www-form-urlencoded but this was no direct cure.
Anyone got any suggestions for me?
I found the answer here NSURLRequest : Post data and read the posted page
It appears that the raw data within the HTTPBody needs to be formatted differently - no JSON at all. The above link has a useful function which I updated slightly
-(NSData*)encodeDictionary:(NSDictionary*)dictionary {
NSMutableArray *parts = [[NSMutableArray alloc] init];
for (NSString *key in dictionary) {
NSString *encodedValue = [[dictionary objectForKey:key] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPasswordAllowedCharacterSet]];
NSString *encodedKey = [key stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPasswordAllowedCharacterSet]];
NSString *part = [NSString stringWithFormat: #"%#=%#", encodedKey, encodedValue];
[parts addObject:part];
}
NSString *encodedDictionary = [parts componentsJoinedByString:#"&"];
return [encodedDictionary dataUsingEncoding:NSUTF8StringEncoding];
}
and ..
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
//NSLog(#"request.header %#", request.allHTTPHeaderFields.description);
// put in the body form using the new function
NSDictionary * parameters = [[NSDictionary alloc] initWithObjectsAndKeys:#"authorization_code",#"grant_type",authorisationCode,#"code",redirectUri,#"redirect_uri", nil ];
NSData * requestBodyData = [self encodeDictionary:parameters];
request.HTTPBody = requestBodyData;

Method always re-writing json file

NSURL *url = [NSURL URLWithString:#"file://localhost/Users/admin/Desktop/JSON/vivijson.json"];
NSDictionary *regDict = [[NSDictionary alloc] initWithObjectsAndKeys:self.loginString, #"login",
self.nameString, #"name",
self.lastNameString, #"lastName",
self.emailString, #"email",
self.numberString, #"number", nil];
NSError *error;
NSMutableArray *regMutArray = [[NSMutableArray alloc] init];
[regMutArray addObject:regDict];
NSData *jsonConvRegArrayData = [NSJSONSerialization dataWithJSONObject:regMutArray options:NSJSONWritingPrettyPrinted error:&error];
NSString *jsonRegString = [[NSString alloc] initWithData:jsonConvRegArrayData encoding:NSUTF8StringEncoding];
[jsonConvRegArrayData writeToURL:url atomically:YES];
This method are re-writing JSON, and start it again, but i need to add some to my JSON.
You should first read the exiting JSON into a mutable array using JSONObjectWithData using NSJSONReadingMutableContainers as the reading options. Then add the new array element to the mutable array returned by JSONObjectWithData and then convert it back to an JSON using dataWithJSONObject
Here's the code.
NSURL *url = [NSURL URLWithString:#"file://localhost/Users/Shared/vivijson.json"];
NSDictionary *regDict = [[NSDictionary alloc] initWithObjectsAndKeys:#"self.loginString, #"login",
self.nameString, #"name",
self.lastNameString, #"lastName",
self.emailString, #"email",
self.numberString, #"number", nil];
NSError *error;
NSMutableArray *regMutArray = [[NSMutableArray alloc] init];
[regMutArray addObject:regDict];
NSData *data = [NSData dataWithContentsOfURL:url];
NSMutableArray *array = nil;
if (data)
array = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
if (array == nil)
{
array = [[NSMutableArray alloc] init];
}
[array addObjectsFromArray:regMutArray];
NSData *jsonConvRegArrayData = [NSJSONSerialization dataWithJSONObject:array options:NSJSONWritingPrettyPrinted error:&error];
NSString *jsonRegString = [[NSString alloc] initWithData:jsonConvRegArrayData encoding:NSUTF8StringEncoding];
[jsonRegString writeToURL:url atomically:true encoding:NSUTF8StringEncoding error:nil];

Create nested JSON in Objective-C

I'm trying to create JSON that looks like this:
{
"id": "feed/http://feeds.feedburner.com/design-milk",
"title": "Design Milk",
"categories": [
{
"id": "user/category/test",
"label": "test"
}
]
}
I'm doing it with this method:
NSMutableDictionary *req = [NSMutableDictionary #"feed/http://feeds.feedburner.com/design-milk" forKey:#"id"];
[req #"Design Milk" forKey:#"title"];
NSDictionary *tmp = [[NSDictionary alloc] initWithObjectsAndKeys:
#"user/category/test", #"id", #"test", #"label",
nil];
[req setObject:tmp forKey:#"categories"];
NSData *postdata = [NSJSONSerialization dataWithJSONObject:req options:0 error:&error];
However, this isn't working. What am I doing wrong here?
The first line of your code isn't going to compile, so you need to fix that.
The value of "categories" in your example output is an array with one element, which happens to be a dictionary. So you need
NSDictionary* oneCategory = [NSDictionary dictionaryWithObjectsAndKeys:...];
NSArray* categories = [NSArray arrayWithObject:oneCategory];
[req setObject:categories forKey:#"categories"];
And you should really use more modern syntax, like
req [#"categories"] = #[oneCategory];
You were missing an array:
NSMutableDictionary *req =[NSMutableDictionary dictionaryWithObjectsAndKeys:#"feed/http://feeds.feedburner.com/design-milk", #"id", nil];
req[#"title"] = #"Design Milk";
NSDictionary *tmp = [[NSDictionary alloc] initWithObjectsAndKeys:
#"user/category/test", #"id",
#"test", #"label",
nil];
NSMutableArray *arr = [[NSMutableArray alloc] init];
[arr addObject:tmp];
[req setObject:arr forKey:#"categories"];
NSError *error;
NSData *postdata = [NSJSONSerialization dataWithJSONObject:req options:0 error:&error];

How do i get the modhash and cookie from logging into reddit with the api?

NSString *username = #"username";
NSString *password = #"password";
NSURL *loginurl = [NSURL URLWithString:[NSString stringWithFormat:#"http://www.reddit.com/api/login/%#",username]];
NSMutableURLRequest *loginrequest = [NSMutableURLRequest requestWithURL:loginurl];
[loginrequest setHTTPMethod:#"POST"];
NSData *loginRequestBody = [[NSString stringWithFormat:#"api_type=json&user=%#&passwd=%#",username,password] dataUsingEncoding:NSUTF8StringEncoding];
[loginrequest setHTTPBody:loginRequestBody];
NSURLResponse *loginResponse = NULL;
NSError *loginRequestError = NULL;
NSData *loginResponseData = [NSURLConnection sendSynchronousRequest:loginrequest returningResponse:&loginResponse error:&loginRequestError];
NSString *loginResponseString = [[NSString alloc]initWithData:loginResponseData encoding:NSUTF8StringEncoding];
NSLog(#"%#",loginResponseString);
the NSLog prints this: (with some letters replaced)
{"json": {"errors": [], "data": {"modhash":
"j5hq16ukw2f17a9c153xxxxxxxxxa72ad989c96c904d49a97e", "cookie":
"13986184,2012-07-14T12:41:05,349f968b3089af75978xxxxxxxxxxxx761397ba0"}}}
How do i access the modhash and the cookie? I tried
[loginResponseData valueForKey:#"json"];
but it says that the class is not key value coding-compliant for the key json
loginResponseString is an NSString -- it doesn't know if it has JSON inside. You have to parse this JSON to an NSDictionary then you can use its methods to retrieve response data. Try my JSON parser: http://github.com/H2CO3/CarbonateJSON
Example using my CarbonateJSON library:
NSDictionary *parsedResponse = [loginResponseString parseJson];
NSString *modhash = [[[parsedResponse objectForKey:#"json"] objectForKey:#"data"] objectForKey:#"modhash"];
For anyone looking at this after me, you can check out H2CO3's solution, but I found that the easiest solution was using NSJSONSerialization to do it in a supported fashion.
NSError *error;
NSData *jsonData = [loginResponseString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *loginResults = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
NSString *modhash = [[[loginResults valueForKey:#"json"] valueForKey:#"data"]valueForKey:#"modhash"];
worked for me.

parse JSON in objectiveC (SBJSON) objects and arrays

So far I've discovered in JSON that everything enclosed in { } are objects (objC : NSDictionary) and anything enclosed in [ ] is an array (objC : NSArray).
I've read and re-read this article about the subject>
How to parse JSON into Objective C - SBJSON
I have a .json file with the data modeled like this:
http://elbee101.com/dummySchedule.json
...and now for the code:
SBJSON *parser = [[SBJSON alloc] init];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://elbee101.com/dummySchedule.json"]];
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *json_string = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSDictionary *schedule = [parser objectWithString:json_string error:nil];
NSDictionary *day = [schedule objectForKey:#"day"];
NSArray *myList = [day objectForKey:#"name"];
NSLog(#"myList %#", myList);
NSArray *numLaps = [myList objectAtIndex:0];
NSLog(#"numlaps%# ", numLaps);
I'm getting "myList (null)" and "numlaps (null)" from the above code?!#
The question: Can somebody please set me straight on the ordering of objects and arrays with respect to my json data? I want to drill down the tree so that I can access the 'day name', 'session starttime/endtime/sessionname', 'numlaps' & 'class' but I can't seem to get past the 'day' object/array(?)
What you're referring to as schedule is the object enclosed in the outermost {}. Try this:
NSDictionary *json = [parser objectWithString:json_string error:nil];
NSDictionary *schedule = [json objectForKey:#"schedule"];
Then continue as before.
Also, if you're on iOS 5 you can use the NSJSONSerialization class -- using it is pretty much the same, you might get better performance, and you don't have to worry about the hassles of using a third-party library.
call this where ever u need to parse
NSMutableArray *arr=[[NSMutableArray alloc] init];
arr=[[Headparse getArrayFromUrl:#"http://elbee101.com/dummySchedule.json"] retain];
NSLog(#"%#",[arr description]);
[arr release];
write this method as custom class use when ever you need
+(NSMutableArray *) getArrayFromUrl: (NSString *)actionType
{
NSMutableData *responseData1= [NSMutableData data] ;
responseData1 = [NSMutableData dataWithContentsOfURL:[NSURL URLWithString:actionType]];
// NSLog(#"%#",responseData1);
NSString *responseString1 = [[NSString alloc] initWithData:responseData1 encoding:NSUTF8StringEncoding];
//NSLog(#"REs:-->%#",responseString1);
//[responseData1 release];
responseData1 = nil;
NSMutableArray *responseArray = [[NSMutableArray alloc]init];
responseArray = (NSMutableArray *)[responseString1 JSONValue];
// NSLog(#"ghfchfvghv%#",responseArray);
[responseString1 release];
return responseArray;
}
This is how i use NSJsonSerialization for parsing the json object.
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://elbee101.com/dummySchedule.json"]];
NSError *err;
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:data
options:kNilOptions
error:&err]; //
NSDictionary *schedule_dict = [json objectForKey:#"schedule"];
NSArray *days = [schedule_dict objectForKey:#"day"];//Days Array from day Object
NSDictionary *dayOne = [days objectAtIndex:0];
NSDictionary *dayTwo = [days objectAtIndex:1];
NSLog(#"THE DAY ONE : %#",dayOne);
NSLog(#"THE DAY TWO : %#",dayTwo);
Hope this may help you ....Note : If you don't want to go with NSJsonSerailization(consider reading of this) ,but still the parsing of json data like above will applicable in your case too.