SBJSON parser doesn't work on second try - iphone

When I call the SBJsonParser the first time, it's working fine but on the second try, the result is always null. The data format is exactly the same as the first.
Here is the code:
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
// the connection finished loading all data, process...
// Store incoming data into a string
NSString *jsonString = [[NSString alloc] initWithData:self.jsonData encoding:NSUTF8StringEncoding];
NSLog(#"%#",jsonString);
if ( jsonString != nil ) {
// Create SBJSON object to parse JSON
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSDictionary *results =
[parser objectWithString:jsonString error:nil];
NSLog(#"results: %#", results);
if ( [[results objectForKey:#"postalCodes"] count] > 0 ) {
// Build an array from the dictionary for easy access to each entry
NSArray *postalCodes_array = [results objectForKey:#"postalCodes"];
int index = 0;
// Loop through each entry in the dictionary...
for (NSDictionary *dict_item in postalCodes_array)
{
if ( index == 0 ) {
appDelegate.curZip = [dict_item objectForKey:#"postalCode"];
NSLog(#"New Zip: %#", appDelegate.curZip);
break;
}
}
postalCodes_array = nil;
parser = nil;
}
results = nil;
}
jsonString = nil;
}
Here are the print out for NSLog lines above:
First try:
2012-05-27 12:19:13.322[16525:707] {"postalCodes": [{"adminName2":"Union","adminCode2":"039","distance":"0","adminCode1":"NJ","postalCode":"07201","countryCode":"US","lng":-74.2099,"placeName":"Elizabeth","lat":40.661369,"adminName1":"New Jersey"},{"distance":"0.28183","adminCode1":"NJ","postalCode":"07216","countryCode":"US","lng":-74.210939,"placeName":"Elizabeth","lat":40.663778,"adminName1":"New Jersey"},{"distance":"0.28183","adminCode1":"NJ","postalCode":"07215","countryCode":"US","lng":-74.210939,"placeName":"Elizabeth","lat":40.663778,"adminName1":"New Jersey"},{"adminName2":"Union","adminCode2":"039","distance":"1.12041","adminCode1":"NJ","postalCode":"07202","countryCode":"US","lng":-74.221544,"placeName":"Elizabeth","lat":40.65652,"adminName1":"New Jersey"},{"adminName2":"Union","adminCode2":"039","distance":"1.72655","adminCode1":"NJ","postalCode":"07206","countryCode":"US","lng":-74.192487,"placeName":"Elizabeth","lat":40.653207,"adminName1":"New Jersey"}]}
Second Try:
2012-05-28 20:16:16.727 [17151:707] {"postalCodes":[{"adminName2":"Kings","adminCode2":"047","distance":"0","adminCode1":"NY","postalCode":"11230","countryCode":"US","lng":-73.956528,"placeName":"Brooklyn","lat":40.618122,"adminName1":"New York"},{"adminName2":"Kings","adminCode2":"047","distance":"1.38292","adminCode1":"NY","postalCode":"11210","countryCode":"US","lng":-73.946682,"placeName":"Brooklyn","lat":40.628064,"adminName1":"New York"},{"adminName2":"Kings","adminCode2":"047","distance":"2.04126","adminCode1":"NY","postalCode":"11229","countryCode":"US","lng":-73.94749,"placeName":"Brooklyn","lat":40.601094,"adminName1":"New York"},{"adminName2":"Kings","adminCode2":"047","distance":"2.45579","adminCode1":"NY","postalCode":"11204","countryCode":"US","lng":-73.985623,"placeName":"Brooklyn","lat":40.617871,"adminName1":"New York"},{"adminName2":"Kings","adminCode2":"047","distance":"2.70498","adminCode1":"NY","postalCode":"11223","countryCode":"US","lng":-73.974291,"placeName":"Brooklyn","lat":40.597874,"adminName1":"New York"}]}{"postalCodes":[{"adminName2":"Richmond","adminCode2":"085","distance":"0","adminCode1":"NY","postalCode":"10306","countryCode":"US","lng":-74.141922,"placeName":"Staten Island","lat":40.564416,"adminName1":"New York"},{"adminName2":"Richmond","adminCode2":"085","distance":"0.41508","adminCode1":"NY","postalCode":"10313","countryCode":"US","lng":-74.146836,"placeName":"Staten Island","lat":40.564393,"adminName1":"New York"},{"adminName2":"Richmond","adminCode2":"085","distance":"1.66907","adminCode1":"NY","postalCode":"10308","countryCode":"US","lng":-74.152649,"placeName":"Staten Island","lat":40.55181,"adminName1":"New York"},{"adminName2":"Richmond","adminCode2":"085","distance":"3.76947","adminCode1":"NY","postalCode":"10312","countryCode":"US","lng":-74.179165,"placeName":"Staten Island","lat":40.545745,"adminName1":"New York"},{"adminName2":"Richmond","adminCode2":"085","distance":"4.41459","adminCode1":"NY","postalCode":"10314","countryCode":"US","lng":-74.147218,"placeName":"Staten Island","lat":40.603915,"adminName1":"New York"}]}
2012-05-28 20:16:16.760 [17151:707] error: Error Domain=org.brautaset.SBJsonParser.ErrorDomain Code=0 "Token 'start of object' not expected after outer-most array or object" UserInfo=0x176560 {NSLocalizedDescription=Token 'start of object' not expected after outer-most array or object}
2012-05-28 20:16:16.761 [17151:707] results: (null)
As you can see, I am doing the init every time. Not sure why it's not working. Any suggestion is appreciated.
Thank you

In your second try the JSON is not valid. That is why it is not being parsed. You can check it here: http://jsonlint.com/
At the end of the JSON string it seems like some junk has been inserted. If you format the string you will find the problem at lines 51-53. Replace the following with a comma:
]
}{
"postalCodes":
On closer inspection it looks like you are only interested in placeName == "Elizabeth". At the very end you have one entry where placeName == "Fanwood". So you probably just want to remove lines 51-62.
As an aside, you could use the error parameter to detect problems with your parser.
NSError *error = nil;
NSDictionary *results = [parser objectWithString:jsonString error:&error];
if (error) {
// we have a problem
}

Why an unexpected array braces closing here?in your second json sring?
"placeName":"Elizabeth","lat":40.653207,"adminName1":"New Jersey"}]}{"postalCodes":{"adminName2":"Union","adminCode2":"039","distance":"3.97758","adminCode1":"NJ","postalCode":"07023","countryCode":"US","lng":-74.386762,"placeName":"Fanwood","lat":40.641856,"adminName1":"New Jersey"}]} .
Its not an issue of init.its an error in the jsonstring that you are getting.

Related

NSDictionary to NSString JSON

I am trying to wrap my head around pulling a keys value from a JSON array and saving it as a String for comparison later: The following code makes my app crash when it gets to this section of code. I don't understand why.
My json array looks like so:
[{"User_Id":"CRNA000099","User_Name":"jbliz","User_Fname":"Julia"}]
My xcode:
userarray_login = [NSJSONSerialization JSONObjectWithData:dataURL options:kNilOptions error:&error];
NSDictionary* userType = [userarray_login objectForKey:#"User_Name"];
NSString *userPermission = [userType objectAtIndex:0];
if ([userPermission isEqualToString:#"jbliz"])
{
NSLog(#"I should get the avalue here: %#", userPermission);
}
I am confused between NSDictionary and NSString. Any feedback would be a
NSMutableArray *name=[[[NSMutableArray alloc] initWithArray:[userarray_login valueForKey:#"User_Name"]]retain];
// Get the only all Names into name Array from json Array
NSString *userPermission = [name objectAtIndex:0]; // get the first name from Array
if ([userPermission isEqualToString:#"jbliz"])
{
NSLog(#"I should get the avalue here: %#", userPermission);
}
Json Array : [{"User_Id":"CRNA000099","User_Name":"jbliz","User_Fname":"Julia"},{},...] an array contains Dictionaries.
for this try like,
NSArray * userarray_login = [NSJSONSerialization JSONObjectWithData:dataURL options:kNilOptions error:&error];
for (NSDictionary * dict in userarray_login) {
NSString * name = [dict objectForKey:#"User_Name"];
if ([name isEqualToString:#"jbliz"]) {
NSLog(#"Value is here: %#", name);
}
}
Your json has array of Dictionary you need to follow below steps,
//NSJSONSerialization return you array in userarray_login
userarray_login = [NSJSONSerialization JSONObjectWithData:dataURL options:kNilOptions error:&error];
//You fetch Dictionary from the array
NSDictionary* userType = [userarray_login objectAtIndex:0];
//Fetch NSString value using keyValue
NSString *userPermission = [userType objectForKey:#"User_Name"];
//String comparison
if ([userPermission isEqualToString:#"jbliz"])
{
NSLog(#"I should get the avalue here: %#", userPermission);
}
This is correct code for your stuff.

google places api - json return correct data and then an exception occurs

I'm using google places API,
The json return valid results, In my async methods I'm setting markers per each result, the method ends and all of a sudden i get the following thread 1: EXC_BAD_ACCESS code:2 address:0x9243e8, in the output window i get the following: [71539:c07] -[__NSCFString CGImage]: unrecognized selector sent to instance 0xb19dd10
I have no clue how to debug this, or where to look for the problem, all my parameters look good.
thanks
I suspect what you are doing is as a commenter says, treating the returned JSON object as a type it is not. Specifically, from your error, you are treating a string like an image. Generally, JSON doesn't not contain actually images, so when you deserialize it, you will not get images. In the Google Places API, it does not send you images. Instead, it send you URLs to images. You will have to download the images using the URLs you get from the Places API.
Here is some code I use. This method gets the place list from the API based on a CLLocation and returns it as a much more easily digested NSArray of NSDictionary objects each containing the important met-data pertaining to a place:
-(NSArray*)getPlaceListForLocation:(CLLocation*)inLocation {
NSString* requestStr = [NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/place/nearbysearch/json?key=%#&location=%f,%f&radius=100&sensor=true",self.googleAPIKey,inLocation.coordinate.latitude,inLocation.coordinate.longitude];
NSURL* requestURL = [NSURL URLWithString:requestStr];
NSLog(#"Fetching place data with URL = %#", requestURL);
NSData* requestData = [NSData dataWithContentsOfURL:requestURL];
if ( nil != requestData ) {
NSError* jsonError = nil;
id resultsObj = [NSJSONSerialization JSONObjectWithData:requestData options:0 error:&jsonError];
if ( nil == resultsObj ) {
if ( nil != jsonError ) {
NSLog(#"%#",jsonError.description);
}
return nil;
}
NSArray* itemList = [resultsObj objectForKey:#"results"];
if ( nil == itemList || itemList.count == 0) {
return nil;
}
NSMutableArray* placeList = [NSMutableArray arrayWithCapacity:itemList.count];
for ( NSDictionary* item in itemList ) {
NSString* name = [item objectForKey:#"name"];
NSString* iconURL = [item objectForKey:#"icon"];
NSString* vicinity = [item objectForKey:#"vicinity"];
NSDictionary* geometryDict = [item objectForKey:#"geometry"];
NSDictionary* locationDict = [geometryDict objectForKey:#"location"];
NSMutableDictionary* itemDict = [NSMutableDictionary dictionaryWithCapacity:2];
if ( nil != name ) {
[itemDict setObject:name forKey:#"name"];
}
if (nil != iconURL ) {
[itemDict setObject:iconURL forKey:#"iconurl"];
}
if ( nil != vicinity ) {
[itemDict setObject:vicinity forKey:#"vicinity"];
}
if ( nil != locationDict ) {
NSString* latitudeStr = [locationDict objectForKey:#"lat"];
NSString* longitudeStr = [locationDict objectForKey:#"lng"];
double latitude = [latitudeStr doubleValue];
double longitude = [longitudeStr doubleValue];
CLLocation* placeLoc = [[CLLocation alloc] initWithLatitude:latitude longitude:longitude];
CLLocationDistance distance = [inLocation distanceFromLocation:placeLoc];
[itemDict setObject:[NSNumber numberWithDouble:distance] forKey:#"distance"];
}
[placeList addObject:itemDict];
}
return placeList;
}
return nil;
}
Then I display these in a table view using the returned NSArray as the data source. In order to display the icon, I use something like MKNetworkImageView in order to fetch the icon based on the URL.

Parse json_encoded data into an array to be used for a UIPickerView - Xcode

I'm looking to populate an array to be used in a pickerview. The data for the array is generated from a database table.
I have the following JSON_ENCODED array (created in php):
{"result":
[
{"id":"3","quivername":"Kite Boarding"},
{"id":"4","quivername":"Live and Die in LA"},
{"id":"14","quivername":"Bahamas Planning"},
{"id":"15","quivername":"My Trip to India"},
{"id":"16","quivername":"Snowboarding"}
]
}
UPDATE FOR WEBSERVICE PHP CODE
I run this function as a webservice:
passport($_SESSION['IdUser'])
function passport($userid) {
$result = query("SELECT id, quivername FROM quivers WHERE userid = $userid");
if (!$result['error']) {
print json_encode($result);
} else {
errorJson('Can not get passports');
}
}
function query() {
global $link;
$debug = false;
//get the sql query
$args = func_get_args();
$sql = array_shift($args);
//secure the input
for ($i=0;$i<count($args);$i++) {
$args[$i] = urldecode($args[$i]);
$args[$i] = mysqli_real_escape_string($link, $args[$i]);
}
//build the final query
$sql = vsprintf($sql, $args);
if ($debug) print $sql;
//execute and fetch the results
$result = mysqli_query($link, $sql);
if (mysqli_errno($link)==0 && $result) {
$rows = array();
if ($result!==true)
while ($d = mysqli_fetch_assoc($result)) {
array_push($rows,$d);
}
//return json
return array('result'=>$rows);
} else {
//error
return array('error'=>'Database error');
}
}
I USE THIS CODE IN XCODE TO CONNECT TO THE WEBSERVICE/WEBSITE USING NSNetworking...
-(void)getPassports {
//just call the "passport" command from the web API
[[API sharedInstance] commandWithParams:[NSMutableDictionary dictionaryWithObjectsAndKeys:
#"passport",#"command",
nil]
onCompletion:^(NSDictionary *json)
{
//got passports, now need to populate pickerArray1
if (![json objectForKey:#"error"])
{
//success, parse json data into array for UIPickerview
}
else
//error, no passports
{
// error alert
}
}];
}
I need the following:
1) how can i populate an NSMutable array with the quivername value? I'm trying to get the result to look like this:
pickerArray1 = [[NSMutableArray alloc] initWithObjects:#"Kite Boarding",
#"Live and Die in LA", #"Bahamas Planning", #"My Trip to India", #"Snowboarding",
nil];
I'm assuming I need to run a for loop which would require me to "count" the number of rows in the array first, but I'm not sure. I don't know how to count the number of rows in the json_array or create an NSMutable array.
Thanks in advance...
You should be able to get your NSData from the URL that returns the JSON using [NSData dataWithContentsOfURL:yourURLValue], then pass the data and parse using something similar to what's below based on your JSON:
//INVOKE WEB SERVICE QUERY IN VIEW DID LOAD -- RUNS ASYNC SO WONT BLOCK UI
- (void)viewDidLoad
{
[super viewDidLoad];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData* data = [NSData dataWithContentsOfURL:
#"URLOFYOURWEBSERVICE"]; // <-- may need to cast string to NSURL....
NSMutableArray *quivernames = [self performSelectorOnMainThread:#selector(fetchedData:)
withObject:data waitUntilDone:YES];
});
}
- (NSMutableArray *)fetchedData:(NSData *)responseData {
//parse out the json data
NSError* error;
//ARRAY OR DICT DEPENDING ON YOUR DATA STRUCTURE
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:responseData
options:kNilOptions
error:&error];
//ITERATE AND/OR ADD OBJECTS TO YOUR NEW ARRAY
NSMutableArray* JSONResultValues = [json objectForKey:#"yourKey"];
NSMutableArray* resultValues = [[NSMutableArray alloc] init];
for(int x = 0; x< [JSONResultValues count]; x++){
NSDictionary *tempDictionary = [JSONResultValues objectAtIndex:x];
[resultValues addObject:[tempDictionary objectForKey:#"quivername"]];
}
NSLog(#"Results Count: %#", [JSONResultValues count]);
NSLog(#"Results Count: %#", [resultValues count]);
return resultValues;
}
EDIT: For more info check out this explanation for JSON parsing http://www.raywenderlich.com/5492/working-with-json-in-ios-5
You could try this (untested):
//convert this to NSData, not sure how it is getting into obj-c
{"result":[
{"id":"3","quivername":"Kite Boarding"},
{"id":"4","quivername":"Live and Die in LA"},
{"id":"14","quivername":"Bahamas Planning"},
{"id":"15","quivername":"My Trip to India"},
{"id":"16","quivername":"Snowboarding"}
]};
NSMutableArray* myData = [self fetchedData:responseData];
- (NSMutableArray* )fetchedData:(NSData *)responseData {
//parse out the json data
NSError* error;
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:responseData
options:kNilOptions
error:&error
];
NSMutableArray* quivers = [json objectForKey:#"result"];
return quivers;
}
Wenderlich explains it here...

How to get data from JSON data

I have JSON like this:
[{"ID" : "351", "Name" : "Cam123 ", "camIP" : "xxx.xxx.xxx.xxx",
"Username" : "admin", "Password" : "damin", "isSupportPin" : "1" },
{"ID" : "352", "Name" : "Cam122 ", "camIP" : "xxx.xxx.xxx.xxx",
"Username" : "admin", "Password" : "damin", "isSupportPin" : "0" }
]
I want to get isSupportPin with result: 1 or 0.
if (x == 1)
{
mybutton.enabled = TRUE;
}
else
{
mybutton.enabled = FALSE;
}
How I can do it?
Assuming you have an NSData object with this data in it:
// Your JSON is an array, so I'm assuming you already know
// this and know which element you need. For the purpose
// of this example, we'll assume you want the first element
NSData* jsonData = /* assume this is your data from somewhere */
NSError* error = nil;
NSArray* array = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
if( !array ) {
// there was an error with the structure of the JSON data...
}
if( [array count] > 0 ) {
// we got our data in Foundation classes now...
NSDictionary* elementData = array[0]; // pick the correct element
// Now, extract the 'isSupportPin' attribute
NSNumber* isSupportPin = elementData[#"isSupportPin"];
// Enable the button per this item
[mybutton setEnabled:[isSupportPin boolValue]];
} else {
// Valid JSON data, but no elements... do something useful
}
The above example code snippet assumes you know which element you want to read (I guess these are user lines or something) and that you know what the JSON attribute names are (e.g., if isSupportPin isn't actually defined in the JSON object returned in that array, it will simply return nil, which will always evaluate to NO when you send it -boolValue).
Finally, the above code is written for ARC and requires Xcode 4.5 or Clang 4.1 and a deployment target of iOS 5.0. If you're not using ARC, building with a legacy version of Xcode, or targeting something earlier than 5.0, you'll have to adjust the code.
Here what you have is an NSArray of NSDictionarys. So using SBJSON library you could do as following
SBJsonParser *parser = [SBJsonParser alloc] init];
NSArray *data = [parser objectFromString:youJson];
for (NSDictionary *d in data)
{
NSString *value = [d objectForKey:#"Name"];
}
The library can be found at http://stig.github.com/json-framework/
Follow the below link that my help you.
http://www.xprogress.com/post-44-how-to-parse-json-files-on-iphone-in-objective-c-into-nsarray-and-nsdictionary/
If you want to get data or Dictionary fron JSONData then use bellow code..
NSString *responseString = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
NSArray *resultsArray = [responseString JSONValue];
for(NSDictionary *item in resultsArray)
{
NSDictionary *project = [item objectForKey:#"result"];//use your key name insted of result
NSLog(#"%#",project);
}
and also download JSON Library and tutorial from below link...
http://mobileorchard.com/tutorial-json-over-http-on-the-iphone/

iphone objective-c : string to NSData conversion for json deserialization

I receive json from a webservice into a NSMutableData.
That gets converted into a NSDictionary using TouchJson.
NSDictionary *dictionary = [[CJSONDeserializer deserializer] deserializeAsDictionary:responseData error:&error];
NSString *strData = [dictionary objectForKey:#"cars"];
I then retrieve a string from a key from that dictionary.
The string looks like below
{
b = "http://schemas.datacontract.org/";
car = (
{
"car_name" = "Honda Civic";
year = 2011;
"dealer" = "local honda dealer";
"bought on" = {
nil = 1;
};
"license_number" = 1234567;
status = ReadyToGo;
}
)};
Essentially there can be 'n' records against the 'car' key.
when I try to convert the above to NSData using
NSData *jsonData = [strData dataUsingEncoding:NSUTF8StringEncoding];
and also
NSData *jsonData = [strData dataUsingEncoding:[NSString defaultCStringEncoding]];
but I get
[__NSCFDictionary dataUsingEncoding:]: unrecognized selector sent to instance 0x532bb70
I have tried a few other encodings available and xcode still threw up.
How can I figure out the encoding being used?
This is my first attempt at deserealizing json in objective-c.
What am I missing/doing wrong here?
Thanks
I think it's not a string at all....
change to this and test....
NSDictionary *dictionary = [[CJSONDeserializer deserializer] deserializeAsDictionary:responseData error:&error];
NSDictionary *carsDictionary = [dictionary objectForKey:#"cars"];
NSArray *arrayOfCarDictionaries = [carsDictionary objectForKey:#"car"];