JSON Parsing in iOS 7

2019-01-13 00:06发布

问题:

I am creating an app for as existing website. They currently has the JSON in the following format :

[

   {
       "id": "value",
       "array": "[{\"id\" : \"value\"} , {\"id\" : \"value\"}]"
   },
   {
       "id": "value",
       "array": "[{\"id\" : \"value\"},{\"id\" : \"value\"}]"
   } 
]

which they parse after escaping the \ character using Javascript.

My problem is when i parse it in iOS using the following command :

NSArray *result = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&localError];

and do this :

NSArray *Array = [result valueForKey:@"array"];

Instead of an Array I got NSMutableString object.

  • The website is already in production so I just cant ask them to change their existing structure to return a proper JSON object. It would be a lot of work for them.

  • So, until they change the underlying stucture, is there any way i can make it work in iOS like they do with javascript on their website?

Any help/suggestion would be very helpful to me.

回答1:

The correct JSON should presumably look something like:

[
    {
        "id": "value",
        "array": [{"id": "value"},{"id": "value"}]
    },
    {
        "id": "value",
        "array": [{"id": "value"},{"id": "value"}]
    }
]

But, if you're stuck this the format provided in your question, you need to make the dictionary mutable with NSJSONReadingMutableContainers and then call NSJSONSerialization again for each of those array entries:

NSMutableArray *array = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
if (error)
    NSLog(@"JSONObjectWithData error: %@", error);

for (NSMutableDictionary *dictionary in array)
{
    NSString *arrayString = dictionary[@"array"];
    if (arrayString)
    {
        NSData *data = [arrayString dataUsingEncoding:NSUTF8StringEncoding];
        NSError *error = nil;
        dictionary[@"array"] = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
        if (error)
            NSLog(@"JSONObjectWithData for array error: %@", error);
    }
}


回答2:

Try this simple method....

- (void)simpleJsonParsing
{
    //-- Make URL request with server
    NSHTTPURLResponse *response = nil;
    NSString *jsonUrlString = [NSString stringWithFormat:@"http://domain/url_link"];
    NSURL *url = [NSURL URLWithString:[jsonUrlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];

    //-- Get request and response though URL
    NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url];
    NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];

    //-- JSON Parsing
    NSMutableArray *result = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:nil];
    NSLog(@"Result = %@",result);

    for (NSMutableDictionary *dic in result)
    {
         NSString *string = dic[@"array"];
        if (string)
        {
             NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
             dic[@"array"] = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
        }
        else
        {
             NSLog(@"Error in url response");
        }
    }

}


回答3:

As people just said above, you must use the NSJSONSerialization to deserialise JSON into usable data structures as NSDictionary or NSArray first.

However, if you want to map the content of your JSON to your Objective-C objects, you will have to map each attribute from the NSDictionary/NSArray to your object property. This might be a bit painful if your objects have many attributes.

In order to automatise the process, I recommend you to use the Motis category on NSObject (a personal project) to accomplish it, thus it is very lightweight and flexible. You can read how to use it in this post. But just to show you, you just need to define a dictionary with the mapping of your JSON object attributes to your Objective-C object properties names in your NSObject subclasses:

- (NSDictionary*)mjz_motisMapping
{
    return @{@"json_attribute_key_1" : @"class_property_name_1",
             @"json_attribute_key_2" : @"class_property_name_2",
              ...
             @"json_attribute_key_N" : @"class_property_name_N",
            };
}

and then perform the parsing by doing:

- (void)parseTest
{
    // Some JSON object
    NSDictionary *jsonObject = [...];

    // Creating an instance of your class
    MyClass instance = [[MyClass alloc] init];

    // Parsing and setting the values of the JSON object
    [instance mjz_setValuesForKeysWithDictionary:jsonObject];
}

The setting of the properties from the dictionary is done via KeyValueCoding (KVC) and you can validate each attribute before setting it via KVC validation.

Hoping it helps you as much it helped me.



回答4:

//-------------- get data url--------

NSURLRequest *request=[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://echo.jsontest.com/key/value"]];

NSData *data=[NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSLog(@"response==%@",response);
NSLog(@"error==%@",Error);
NSError *error;

id jsonobject=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];

if ([jsonobject isKindOfClass:[NSDictionary class]]) {
    NSDictionary *dict=(NSDictionary *)jsonobject;
    NSLog(@"dict==%@",dict);
}
else
{
    NSArray *array=(NSArray *)jsonobject;
    NSLog(@"array==%@",array);
}


回答5:

// ----------------- json for localfile---------------------------

NSString *pathofjson = [[NSBundle mainBundle]pathForResource:@"test1" ofType:@"json"];
NSData *dataforjson = [[NSData alloc]initWithContentsOfFile:pathofjson];
arrayforjson = [NSJSONSerialization JSONObjectWithData:dataforjson options:NSJSONReadingMutableContainers error:nil];
[tableview reloadData];

//------------- json for urlfile-----------------------------------

NSString *urlstrng = @"http://www.json-generator.com/api/json/get/ctILPMfuPS?indent=4";
NSURL *urlname = [NSURL URLWithString:urlstrng];
NSURLRequest *rqsturl = [NSURLRequest requestWithURL:urlname];

//------------ json for urlfile by asynchronous----------------------

[NSURLConnection sendAsynchronousRequest:rqsturl queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
    arrayforjson = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
    [tableview reloadData];
}];

//------------- json for urlfile by synchronous----------------------

NSError *error;
NSData *data = [NSURLConnection sendSynchronousRequest:rqsturl returningResponse:nil error:&error];

 arrayforjson = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];

[tableview reloadData];
} ;


回答6:

  • You may always unescape the jsonData before deliver it to NSJSONSerialization. Or you may use the string got to construct another json object to get the array.

  • NSJSONSerialization is doing right, the value in your example should be a string.



回答7:

As another answer has said, that value is a string.

You can get around it by turning that string into data, as it seems to be a valid json string and then parse that json data object back into an array which you can add to your dictionary as the value for the key.



回答8:

 NSError *err;
    NSURL *url=[NSURL URLWithString:@"your url"];
    NSURLRequest *req=[NSURLRequest requestWithURL:url];
    NSData *data = [NSURLConnection sendSynchronousRequest:req returningResponse:nil error:&err];
    NSDictionary *json=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
    NSArray * serverData=[[NSArray alloc]init];
    serverData=[json valueForKeyPath:@"result"];


回答9:

NSString *post=[[NSString stringWithFormat:@"command=%@&username=%@&password=%@",@"login",@"username",@"password"]stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

    NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.blablabla.com"]];

   [request setHTTPMethod:@"POST"];

   [request setValue:@"x-www-form-urlencoded" forHTTPHeaderField:@"content-type"];
    [request setHTTPBody:[NSData dataWithBytes:[post UTF8String] length:strlen([post UTF8String])]];

   NSData *data=[NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];

    id jsonobject=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];

    if ([jsonobject isKindOfClass:[NSDictionary class]])
    {

        NSDictionary *dict=(NSDictionary *)jsonobject;
        NSLog(@"dict==%@",dict);

    }
    else
    {

        NSArray *array=(NSArray *)jsonobject;
        NSLog(@"array==%@",array);
    }


回答10:

May be this will help you.

- (void)jsonMethod
{
    NSMutableArray *idArray = [[NSMutableArray alloc]init];
    NSMutableArray *nameArray = [[NSMutableArray alloc]init];
    NSMutableArray* descriptionArray = [[NSMutableArray alloc]init];

    NSHTTPURLResponse *response = nil;
    NSString *jsonUrlString = [NSString stringWithFormat:@"Enter your URL"];
    NSURL *url = [NSURL URLWithString:[jsonUrlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];


    NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url];
    NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];

    NSDictionary *result = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:nil];
    NSLog(@"Result = %@",result);


    for (NSDictionary *dic in [result valueForKey:@"date"])
    {
        [idArray addObject:[dic valueForKey:@"key"]];
        [nameArray addObject:[dic valueForKey:@"key"]];
        [descriptionArray addObject:[dic valueForKey:@"key"]];

    }

}


回答11:

JSON default method :

+ (NSDictionary *)stringWithUrl:(NSURL *)url postData:(NSData *)postData httpMethod:(NSString *)method
{
    NSDictionary *returnResponse=[[NSDictionary alloc]init];

    @try
    {
        NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url
                                                                  cachePolicy:NSURLRequestReloadIgnoringCacheData
                                                              timeoutInterval:180];
        [urlRequest setHTTPMethod:method];

        if(postData != nil)
        {
            [urlRequest setHTTPBody:postData];
        }

        [urlRequest setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
        [urlRequest setValue:@"application/json" forHTTPHeaderField:@"Accept"];
        [urlRequest setValue:@"text/html" forHTTPHeaderField:@"Accept"];

        NSData *urlData;
        NSURLResponse *response;
        NSError *error;
        urlData = [NSURLConnection sendSynchronousRequest:urlRequest
                                        returningResponse:&response
                                                    error:&error];
        returnResponse = [NSJSONSerialization
                          JSONObjectWithData:urlData
                          options:kNilOptions
                          error:&error];
    }
    @catch (NSException *exception)
    {
        returnResponse=nil;
    }
    @finally
    {
        return returnResponse;
    }
}

Return method:

+(NSDictionary *)methodName:(NSString*)string{
    NSDictionary *returnResponse;
    NSData *postData = [NSData dataWithBytes:[string UTF8String] length:[string length]];
    NSString *urlString = @"https//:..url....";
    returnResponse=[self stringWithUrl:[NSURL URLWithString:urlString] postData:postData httpMethod:@"POST"];    
    return returnResponse;
}


回答12:

@property NSMutableURLRequest * urlReq;

@property NSURLSession * session;

@property NSURLSessionDataTask * dataTask;

@property NSURLSessionConfiguration * sessionConfig;

@property NSMutableDictionary * appData;

@property NSMutableArray * valueArray; @property NSMutableArray * keysArray;

  • (void)viewDidLoad { [super viewDidLoad]; self.valueArray = [[NSMutableArray alloc]init]; self.keysArray = [[NSMutableArray alloc]init]; self.linkString = @"http://country.io/names.json"; [self getData];

-(void)getData
{ self.urlReq = [[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:self.linkString]];

self.sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];

self.session = [NSURLSession sessionWithConfiguration:self.sessionConfig];

self.dataTask = [self.session dataTaskWithRequest:self.urlReq completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    self.appData = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

    NSLog(@"%@",self.appData);
    self.valueArray=[self.appData allValues];
    self.keysArray = [self.appData allKeys];


}];
[self.dataTask resume];


回答13:

#define FAVORITE_BIKE @"user_id=%@&bike_id=%@"
@define FAVORITE_BIKE @"{\"user_id\":\"%@\",\"bike_id\":\"%@\"}"
NSString *urlString = [NSString stringWithFormat:@"url here"];
NSString *jsonString = [NSString stringWithFormat:FAVORITE_BIKE,user_id,_idStr];
NSData *myJSONData =[jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:@"POST"];
NSMutableData *body = [NSMutableData data];
[body appendData:[NSData dataWithData:myJSONData]];
[request setHTTPBody:body];
NSError *error;
NSURLResponse *response;
NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *str = [[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];
if(str.length > 0)
{
    NSData* data = [str dataUsingEncoding:NSUTF8StringEncoding];
    NSMutableDictionary *resDict =[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
}


回答14:

-(void)responsedata
{

    NSMutableURLRequest *request=[[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:replacedstring]];

    [request setHTTPMethod:@"GET"];
    NSURLSessionConfiguration *config=[NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session=[NSURLSession sessionWithConfiguration:config];
    NSURLSessionDataTask *datatask=[session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error) {
            NSLog(@"ERROR OCCURE:%@",error.description);
        }
        else
        {
            NSError *error;
            NSMutableDictionary *responseDict=[[NSMutableDictionary alloc]init];
            responseDict=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];


            if (error==nil)
            {


             // use your own array or dict for fetching as per your key..  


                _responseArray =[[NSMutableArray alloc]init];

                _geometryArray=[[NSMutableArray alloc]init];



                _responseArray=[responseDict valueForKeyPath:@"result"];

                referncestring =[[_photosArray objectAtIndex:0]valueForKey:@"photo_reference"];

                _geometryArray=[_responseArray valueForKey:@"geometry"];
               // _locationArray=[[_geometryArray objectAtIndex:0]valueForKey:@"location"];
                _locationArray=[_geometryArray valueForKey:@"location"];
                latstring=[_locationArray valueForKey:@"lat"];
                lngstring=[_locationArray valueForKey:@"lng"];


        coordinates = [NSMutableString stringWithFormat:@"%@,%@",latstring,lngstring];




            }

        }

        dispatch_sync(dispatch_get_main_queue(), ^
                      {



                         // call the required method here..

                      });




    }];
    [datatask resume];   //dont forget it

    }