passing a variable from a JSON array in Objective-C - objective-c

I am pulling information from a web page into my app in the form of JSON arrays. The arrays themselves are not static in that some of the items in the arrays will change from time to time. The first array contains various fields but the problem in this case is that it will send a variable which has to be passed to a different function elsewhere in my code to form part of a url. For example, the first array would be something like:
{"i_one":"some info","i_two":"some more info","p_id":"3"}]
The p_id part, i.e.:3, needs to be passed into the example url shown below to replace the {ID}.
"http://http://www.somesite.com/json/files/project_%#",p_id
How can I do this when the variable(s) received from the array are only available within the function that the array is parsed in?
Ok so,
First the array is pulled from a url via this:
#define getDataURL #"http://www.somesite.com/json/files/jarray.txt"
Then the data is retrieved and parsed like this:
//Retrieve data
NSURL * url = [NSURL URLWithString:getDataURL];
NSData * data = [NSData dataWithContentsOfURL:url];
jsonArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
//Loop through Json Array
for (int i = 0; i < jsonArray.count; i++)
{ NSString * bID= [[jsonArray objectAtIndex:i] objectForKey:#"p_id"];}
This seems to work fine to this point.
However, elsewhere in the code in another function, I then try to use p_id and pass it into a url like this:
NSString *imageUrl = NSString stringWithFormat:#"http://www.somesite.com/json/files/project_%# ", [bID];
[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:imageUrl]] queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
cell.ThumbImage.image = [UIImage imageWithData:data];}];
At this point I get "use of undeclared identifier bID"

OK, first off. Your array is actually a dictionary.
Using NSJSONSerialization will give you an object like...
NSDictionary *dictionary = #{
#"i_one" : #"some info",
#"i_two" : #"some more info",
#"p_id" : #"3"
};
To put the pid into a string you can use this...
NSString *string = [NSString stringWithFormat:#"http://www.somesite.com/json/files/project_%#", dictionary[#"p_id"]];

Related

Converting a JSON file to NSMutableDictionary in Objective C?

I have a json file that looks like this:
{
"data":
{
"level": [
{
//bunch of stuff
}
]
}
}
Now I want to convert that into a array of levels that I can access. If I take away the {"data: part, then I can use this:
NSData *allLevelsData = [[NSData alloc] initWithContentsOfFile:fileLoc];
NSError *error = nil;
NSMutableDictionary *allLevels = [NSJSONSerialization JSONObjectWithData:allLevelsData options:kNilOptions error:&error];
if(!error){
NSMutableArray *level = allLevels[#"level"];
for (NSMutableDictionary *aLevel in level){
//do stuff with the level...
But I have to have the {"data: as part of the file, and I can't figure out how to get a NSData object out of the existing NSData object. Any ideas?
Don't you need to pull the level NSArray out of the data NSDictionary first?
NSData *allLevelsData = [[NSData alloc] initWithContentsOfFile:fileLoc];
NSError *error = nil;
NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:allLevelsData options:kNilOptions error:&error];
if(!error){
NSArray *levels = dataDictionary[#"data"][#"level"];
for (NSDictionary *aLevel in levels){
//do stuff with the level...
You won't get mutable objects back by default and declaring the variables as mutable doesn't make them so. Take a mutableCopy of the result instead (assuming you really do need mutability).
Why are you trying to prune ahead of time? If you decode the original JSON, you'll be able to extract the level array from the data dict in the decoded dict.
It's not clear what else you're trying to accomplish or why you are going the path you ask about. Note, this doesn't necessarily mean your path is wrong, just that without a clearer indication of what goal you're really trying to accomplish or what you've actually tried (and errored/failed, along with how it failed), you're likely only to get vague/general answers like this.

Replace " in string with \"

I am trying to send a string to the server. I encode it and set it as the body of an HTTP request using
[request setHTTPBody:[body dataUsingEncoding:NSUTF8StringEncoding]];
Where body is the string.It has to be in json format.
For example
body = [NSString stringWithFormat:#"{\"emailBody\":\"%#\"}",string] ;
should be valid
But i accept string from user and it may contain double quotes.Therefore i have to escape double quotes(") in it.
For example if want to send just one "
{\"emailBody\":\"\\\"\"}
(harddcoded) returns positive response from server.
So i would like to create such a string from the original string.I tried the following
string = [string stringByReplacingOccurencesOfString:#"\"" withString:#"\\\\\""];
But it did not work.I got \" in my test email.Thats as far as i have been able to get.
Am I taking the right approach ??I would appreciate it if someone would point me in the right direction.Thanks
You should generate your JSON directly from a dictionary. That'll take care of all the encoding automatically for you:
NSDictionary *body = #{#"emailBody": string};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:body options:0 error:&error];
if (!jsonData) {
NSLog(#"Got an error: %#", error);
} else {
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
[request setHTTPBody:jsonString];
}

How to get same JSON string output on iOS and Rails?

I have a JSON document on iOS and an identical document in Rails. When I serialize it on iOS, I need it to be character-for-character equivalent to the serialized string from Rails. However, when I try this, the outputs are mostly the same, but not quite.
On iOS:
id jsonObj;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonObj options:0 error:nil];
NSString *string = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
On the Ruby side:
jsonObj // contains exactly the same content as the objc version
string = JSON.generate(jsonObj)
The issue I'm having is that Ruby's JSON.generate() doesn't output a JSON string in the same format as NSJSONSerialization on iOS. Is there any way to make them behave the same? Or is there another serialization method I can use to get consistent results on iOS and Rails?
One difference between the two that I spotted was that the original object had the text "N/A" in it. Rails outputs this as-is, while iOS escapes it to "N\ /A". Is there another string encoding option I can use on the iOS side to fix this?
Edit:
Here's a better example:
id json = #{ #"str": #"N/A" };
NSError *error = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:json options:0 error:&error];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(#"jsonString = '%#'", jsonString);
// prints "jsonString = '{"str":"N\/A"}'"
And the ruby equivalent:
json = { "str" => "N/A" }
jsonString = JSON.generate(json)
puts "jsonString = '#{jsonString}'"
// prints "jsonString = '{"str":"N/A"}'"
I also wrote both outputs to files and compared them again, with the same results.

The most basic way to retrieve a JSON array in objective-c? [duplicate]

This question already has answers here:
How to use NSJSONSerialization
(12 answers)
Closed 9 years ago.
Basically I have a JSON array on a webpage, the array works fine on the webpage and I can pull it into objective-c as a string, but I need to pull it into objective-c as an array. Can anybody tell me the most basic way to do this? I've seen some tutorials that do this but most of them are arrays of objects in JSON.
Here's my objective-c code to pull the information as a string is:
//create string to contain URL address for PHP file, the file name is index.php and the parameter: name is passed to the file
NSString *strURL = [NSString stringWithFormat:#"http://localhost:8888/page4.php?name=%#", _txtName.text];
//to execute PHP code
NSData *dataURL = [NSData dataWithContentsOfURL:[NSURL URLWithString: strURL]];
//to recieve the returned value
NSString *strResult = [[NSString alloc] initWithData:dataURL encoding:NSUTF8StringEncoding];
NSLog(#"%#", strResult);
Here is the PHP/JSON code for my webpage.
<?php
if (isset ($_GET["name"]))
$name = $_GET["name"];
else
$name = "NULL";
// Make a MySQL Connection
mysql_connect("localhost", "root", "root") or die(mysql_error());
mysql_select_db("test") or die(mysql_error());
// Retrieve all the data from the "example" table
$result = mysql_query("SELECT * FROM user WHERE name = '$name'")
or die(mysql_error());
// store the record of the "example" table into $row
$row = mysql_fetch_array( $result );
$array = array(
"0" => $row['id'],
"1" => $row['name'],
);
$json_array = json_encode($array);
echo $json_array;
?>
As of iOS 5, Apple provides a built-in class to do this for you. You can set options to make the returned NSArray and NSDictionary containers mutable, or the returned leaf objects mutable. It operates on NSData, rather than NSString. It's simple to use:
NSError *error = nil;
NSArray *parsedArray = [NSJSONSerialization JSONObjectWithData:dataUrl
options:kNilOptions
error:&error];
you can convert your json response to array using following code
NSError* error = nil;
NSArray *jsonArray = [NSJSONSerialization
JSONObjectWithData:responseData
options:kNilOptions
error:&error];

EXC_BAD_ACCESS memory error under ARC

In the method below I'm receiving "EXC_BAD_ACCESS" on the line containing the "urlString" variable. My research suggests that this error occurs when the program sends a message to a variable that has already been released. However since I'm using ARC I'm not manually releasing memory. How can I prevent ARC from releasing this variable too soon?
-(NSMutableArray *)fetchImages:(NSInteger *)count {
//prepare URL request
NSString *urlString = [NSString stringWithFormat:#"http://foo.example.com/image?quantity=%#", count];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]];
//Perform request and get JSON as a NSData object
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
//Parse the retrieved JSON to an NSArray
NSError *jsonParsingError = nil;
NSArray *imageFileData = [NSJSONSerialization JSONObjectWithData:response options:0 error:&jsonParsingError];
//Create an Array to store image names
NSMutableArray *imageFileNameArray;
//Iterate through the data
for(int i=0; i<[imageFileData count];i++)
{
[imageFileNameArray addObject:[imageFileData objectAtIndex:i]];
}
return imageFileNameArray;
}
Your problem has nothing to do with ARC. NSInteger isn't a class, so you don't want to be using the %# format. %# is going to send a description method to what the system thinks is an object, but when it turns out not to be one - CRASH. To solve your problem, you have two options:
You might want:
NSString *urlString =
[NSString stringWithFormat:#"http://foo.example.com/image?quantity=%d",
*count];
Make sure the count pointer is valid first!
You might need to change your method signature to be:
-(NSMutableArray *)fetchImages:(NSInteger)count;
and then change the urlString line as follows:
NSString *urlString =
[NSString stringWithFormat:#"http://foo.example.com/image?quantity=%d",
count];
You'll also need to fix all of the callers to match the new signature.
The second option seems more "normal" to me, but without more of your program it's impossible to be more specific.
you also may want to alloc and init the
NSMutableArray *imageFileNameArray;
before adding objects to it, otherwise you'll keep crashing. So you'd have
//Create an Array to store image names
NSMutableArray *imageFileNameArray = [[NSMutableArray alloc] init];