I call my webservice using the getPath method like so:
[[AFTwitterAPIClient sharedClient] getPath:#"GetWineCategoryList"
parameters:parameters success:^(AFHTTPRequestOperation *operation, id JSON) {
NSLog(#"JSON = %#",JSON);
NSMutableArray *mutableTweets = [NSMutableArray arrayWithCapacity:[JSON count]];
for (NSDictionary *attributes in mutableTweets) {
Tweet *tweet = [[Tweet alloc] initWithAttributes:attributes];
[mutableTweets addObject:tweet];
}
if (block) {
block([NSArray arrayWithArray:mutableTweets], nil);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if (block) {
block([NSArray array], error);
}
}];
It always outputs as NSData. If I convert this NSData to a string I get a JSON String.
JSON = <5b7b2243 61746567 6f72794e 616d6522 3a224f54 48455222 7d2c7b22 43617465 676f7279 4e616d65 223a2252 4544227d 2c7b2243 61746567 6f72794e 616d6522 3a22524f 5345227d 2c7b2243 61746567 6f72794e 616d6522 3a225748 49544522 7d5d>
Why won't it convert to an NSArray?
You can use the NSJSONSerialization Class to convert your NSData object to an NSArray.
NSArray *array = (NSArray*)[NSJSONSerialization JSONObjectWithData:JSON
options:0
error:&error];
This assumes you know that your JSON is of array type and not dictionary type.
Related
This question already has answers here:
How do I parse JSON with Objective-C?
(5 answers)
Closed 6 years ago.
I have the following json:
NSString *s = #"{"temperature": -260.65, "humidity": 54.05, "time": "2016-03-14T09:46:48Z", "egg": 1, "id": 6950, "no2": 0.0}";
I need to extract data from json to strings
NSString temperature
NSString humidity
NSString no2
How to do it properly?
you can use NSJSONSerialization class. first you need to convert your string to an NSData object after that you will get the JSON data. have a look on the code
// json s string for NSDictionary object
NSString *s = #"{\"temperature\": -260.65, \"humidity\": 54.05, \"time\": \"2016-03-14T09:46:48Z\", \"egg\": 1, \"id\": 6950, \"no2\": 0.0}";
// comment above and uncomment below line, json s string for NSArray object
// NSString *s = #"[{\"ID\":{\"Content\":268,\"type\":\"text\"},\"ContractTemplateID\":{\"Content\":65,\"type\":\"text\"}}]";
NSData *jsonData = [s dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
// Note that JSONObjectWithData will return either an NSDictionary or an NSArray, depending whether your JSON string represents an a dictionary or an array.
id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
if (error) {
NSLog(#"Error parsing JSON: %#", error);
}
else
{
if ([jsonObject isKindOfClass:[NSArray class]])
{
NSLog(#"it is an array!");
NSArray *jsonArray = (NSArray *)jsonObject;
NSLog(#"jsonArray - %#",jsonArray);
}
else {
NSLog(#"it is a dictionary");
NSDictionary *jsonDictionary = (NSDictionary *)jsonObject;
NSLog(#"jsonDictionary - %#",jsonDictionary);
}
}
After making the NSURL Request in the completion block u can do this:-
NSMutableDictionary *s = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
NSString *temperature =[s objectForKey:#"temperature"];
NSString *humidity = [s objectForKey:#"humidity"];
I receive this JSON string from a web process
{
"result":"ok",
"description":"",
"err_data":"",
"data":[
{
"id":"14D19A9B-3D65-4FE2-9ACE-4C2D708DAAD8"
},
{
"id":"8BFD10B8-F5FD-4CEE-A307-FE4382A0A7FD"
}
]
}
and when I use the following to get the data:
NSError *jsonError = nil;
NSData *objectData = [ret dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *json= [NSJSONSerialization JSONObjectWithData: objectData options:kNilOptions error: &jsonError];
NSLog(#"data: %#",[json objectForKey:#"data"]);
it gets logged as:
(
{
id = "14D19A9B-3D65-4FE2-9ACE-4C2D708DAAD8";
},
{
id = "8BFD10B8-F5FD-4CEE-A307-FE4382A0A7FD";
}
)
How can I parse the data as an NSDictionary with value and keys?
The web returns an object that has a property which is an array of objects, so...
NSDictionary *json= // your code
NSArray *array = json[#"data"];
for (NSDictionary *element in array) {
NSLog(#"%#", element);
// or, digging a little deeper
NSString *idString = element[#"id"];
NSLog(#"id=%#", idString);
}
I have several objects that I want to store in an array. What is the way to do this in objective-c? I have been looking into NSMutableDictionary but have had no luck.
In my code below, I am iterating through an array of strings, making a network call for each string, and getting an object back for each string. I want to store my objects in a list that I can access later.
-(void) setPictures {
for(id item in self.phraseWordsArray) {
AFNetworkingAPIClient *netowrkingObject = [[AFNetworkingAPIClient alloc] init];
[netowrkingObject getPhotoForWord:item success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"responseObject=%#",responseObject);
self.test = responseObject;
[self printOutJSON];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"error=%#",error);
}];
}
}
It looks like NSMutableArray is what you need, am i correct?
You can store your response objects into an NSMutableArray that is a property on the UIViewController calling this code, or elsewhere. See the following for an example scenario:
// In your interface...
#property (nonatomic,strong) NSMutableArray *responseObjects;
// ... Later in code
self.responseObjects = [NSMutableArray array];
- (void)setPictures {
for(id item in self.phraseWordsArray) {
AFNetworkingAPIClient *netowrkingObject = [[AFNetworkingAPIClient alloc] init];
[netowrkingObject getPhotoForWord:item success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"responseObject=%#",responseObject);
self.test = responseObject;
[self printOutJSON];
if (responseObject) {
[self.responseObjects addObject:responseObject];
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"error=%#",error);
}];
}
}
I'm trying to handle Facebook JSON data and transform it into a NSMutable Dictionary, but I'm getting (null) when I try to print the data. Although when I try to do a count, I get a number.
User_likes is NSMutableDictionary which is globally defined. I'm getting (null) on this line:
NSLog(#"User likes: %#", user_likes);
This is my code:
NSString *query =
#"SELECT page_id, type FROM page_fan WHERE uid = me() ";
// Set up the query parameter
NSDictionary *queryParam = #{ #"q": query };
// Make the API request that uses FQL
[FBRequestConnection startWithGraphPath:#"/fql"
parameters:queryParam
HTTPMethod:#"GET"
completionHandler:^(FBRequestConnection *connection,
id results,
NSError *error) {
if (error) {
NSLog(#"Error: %#", [error localizedDescription]);
} else {
user_likes = [NSJSONSerialization JSONObjectWithData:results options:kNilOptions error:&error];
NSLog(#"User likes: %#", user_likes);
NSInteger* n_user_likes = [results count];
NSInteger* n_user_likes2 = [user_likes count];
NSLog(#"n user likes %qi", n_user_likes);
NSLog(#"n user likes2 %qi", n_user_likes2);
id val = nil;
id values = [[user_likes allKeys] objectAtIndex:0 ];
NSLog(#"values id %#", values);
When I print results, I get a lot of data from Facebook, this is a sample of it:
data = (
{
"page_id" = 253370381511811;
type = "PUBLIC FIGURE";
},
{
"page_id" = 148389618201;
type = "LOCAL BUSINESS";
},
{
"page_id" = 213631462169238;
type = COMMUNITY;
},
{
"page_id" = 162297750451425;
type = "NON-PROFIT ORGANIZATION";
},
{
"page_id" = 503620106320217;
type = "MEDIA/NEWS/PUBLISHING";
},
you can't do directly
user_likes = [NSJSONSerialization JSONObjectWithData:results options:kNilOptions error:&error];
you need first create a dictionary with the data in results like this:
NSDictionary *dictionary = [NSDictionary dictionaryWithJSONData:results];
user_likes = [NSString stringWithFormat:#"%d",[[dictionary objectForKey:#"value_of_the_likes"] intValue]];
NSLog(#"%#",user_likes);
NSLog(#"%#",dictionary);
EDIT:
Please, create this class to your project and import in the class where you need use this.
#import <Foundation/Foundation.h>
#interface NSDictionary (JSONExtensions)
+(NSDictionary*)dictionaryWithJSONData:(NSData*)data;
-(NSData*)JSONValue;
-(NSString*)JSONString;
#end
#implementation NSDictionary(JSONExtensions)
+(NSDictionary*)dictionaryWithJSONData:(NSData*)data{
NSError *error = nil;
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
if(error){
NSLog(#"%#",error);
return nil;
};
return result;
}
-(NSData*)JSONValue{
NSError *error = nil;
NSData *result = [NSJSONSerialization dataWithJSONObject:self options:kNilOptions error:&error];
if(error){
NSLog(#"%#",error);
return nil;
};
return result;
}
-(NSString*)JSONString{
return [[NSString alloc] initWithData:self.JSONValue encoding:NSUTF8StringEncoding];
}
#end
Hope it can help you.
maybe you forget set up options:
NSJSONReadingOptions options = NSJSONReadingAllowFragments | NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves;
user_likes = [NSJSONSerialization JSONObjectWithData:results options:options error:&error];
i hope this be useful for you!
UPDATE:
Check this :
NSJsonSerialzation not parsing results from Facebook - Cocoa error 3840
Let me know if that helps you!
I've looked through SO and Google and haven't found a similiar issue to this. I feel like the answer is staring me in the face and I just need another set of eyes.
I'm using AFNetworking to connect to the Stripe.com API. Specifically I'm using AFHTTPClient postPath to send data to an endpoint, charges. Stripe requires the request to be encoded as application/x-www-form-urlencoded so I can't use JSON encoding.
The problem I'm running into is that I have a Charge object and a Card object. Card is a property on Charge and I convert both Charge and Card to NSDictionary's (Card is an dictionary inside of the Charge dictionary) and then pass them in as the parameters on the request like so:
NSDictionary *parameters = [ChargeRequest convertToDictionary:request];
[[StripeAPIClient sharedClient] postPath:#"charges" parameters:parameters
success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"Response: %#", responseObject);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", [error localizedDescription]);
NSLog(#"Response: %#", operation.responseString);
}];
When I do this, with AFHttpClient's parameterEncoding property set to AFFormURLParameterEncoding, Stripe returns this error:
"error": {
"message": "Invalid token id: {\n \"exp_month\" = 10;\n \"exp_year\" = 2016;\n number = 4242111111111111;\n}",
"type": "invalid_request_error"
}
The values in the error are specifically the key/values on the Card object after converting it. Here is the code I use for the conversion:
return [[NSDictionary alloc] initWithObjectsAndKeys:request.number, #"number", [NSNumber numberWithInt:10], #"exp_month", [NSNumber numberWithInt:2016], #"exp_year", nil];
Any advice on what do to get rid of the invalid tokens being put in this NSDictionary? Am I focusing on the wrong thing?
Thanks!
AFNetworking support only AFFormURLParameterEncoding with 1 level of parameters.
I'm writing a fix for that
replace AFQueryStringFromParametersWithEncoding implementation in AFHTTPClient by
extern NSArray * AFQueryParametersFromParametersAtBaseKeyWithEncoding(id parameters, NSString *baseKey, NSStringEncoding encoding);
extern NSArray * AFQueryParametersFromParametersDictionaryAtBaseKeyWithEncoding(NSDictionary *parameters, NSString *baseKey, NSStringEncoding encoding);
extern NSArray * AFQueryParametersFromParametersArrayAtBaseKeyWithEncoding(NSArray *parameters, NSString *baseKey, NSStringEncoding encoding);
extern NSArray * AFQueryStringComponentFromParameterAtBaseKeyWithEncoding(id parameter, NSString *key, NSStringEncoding encoding);
NSString * AFQueryStringFromParametersWithEncoding(NSDictionary *parameters, NSStringEncoding encoding) {
NSMutableArray *mutableParameterComponents = [NSMutableArray array];
[mutableParameterComponents addObjectsFromArray:AFQueryParametersFromParametersAtBaseKeyWithEncoding(parameters,nil,encoding)];
return [mutableParameterComponents componentsJoinedByString:#"&"];
}
NSArray * AFQueryParametersFromParametersAtBaseKeyWithEncoding(id parameters, NSString *baseKey, NSStringEncoding encoding)
{
NSMutableArray *mutableParameterComponents = [NSMutableArray array];
if([parameters isKindOfClass:[NSDictionary class]]) {
[mutableParameterComponents addObjectsFromArray:AFQueryParametersFromParametersDictionaryAtBaseKeyWithEncoding(parameters,baseKey,encoding)];
}
else if([parameters isKindOfClass:[NSArray class]]) {
[mutableParameterComponents addObjectsFromArray:AFQueryParametersFromParametersArrayAtBaseKeyWithEncoding(parameters,baseKey,encoding)];
}
else {
[mutableParameterComponents addObject:AFQueryStringComponentFromParameterAtBaseKeyWithEncoding(parameters,baseKey,encoding)];
}
return mutableParameterComponents;
}
NSArray * AFQueryParametersFromParametersDictionaryAtBaseKeyWithEncoding(NSDictionary *parameters, NSString *baseKey, NSStringEncoding encoding)
{
NSMutableArray *mutableParameterComponents = [NSMutableArray array];
id key = nil;
NSEnumerator *enumerator = [parameters keyEnumerator];
while ((key = [enumerator nextObject])) {
NSString *newKey = baseKey?[NSString stringWithFormat:#"%#[%#]",baseKey,key]:key;
[mutableParameterComponents addObjectsFromArray:AFQueryParametersFromParametersAtBaseKeyWithEncoding([parameters valueForKey:key],newKey,encoding)];
}
return mutableParameterComponents;
}
NSArray * AFQueryParametersFromParametersArrayAtBaseKeyWithEncoding(NSArray *parameters, NSString *baseKey, NSStringEncoding encoding)
{
NSMutableArray *mutableParameterComponents = [NSMutableArray array];
for (id value in parameters) {
NSString* newKey = [NSString stringWithFormat:#"%#[]",newKey];
[mutableParameterComponents addObjectsFromArray:AFQueryParametersFromParametersAtBaseKeyWithEncoding(value,newKey,encoding)];
}
return mutableParameterComponents;
}
NSArray * AFQueryStringComponentFromParameterAtBaseKeyWithEncoding(id parameter, NSString *key, NSStringEncoding encoding)
{
return [NSString stringWithFormat:#"%#=%#", AFURLEncodedStringFromStringWithEncoding([key description], encoding), AFURLEncodedStringFromStringWithEncoding([parameter description], encoding)];
}
I'm just writing the same code for multipart requests and submit a pull request to AFNetworking