NSJSONSerialization का उपयोग कैसे करें


156

मेरे पास एक JSON स्ट्रिंग है (PHP की json_encode()तरह जो इस तरह दिखता है:

[{"id": "1", "name":"Aaa"}, {"id": "2", "name":"Bbb"}]

मैं अपने iPhone ऐप के लिए इसे किसी प्रकार की डेटा संरचना में पार्स करना चाहता हूं। मैं सबसे अच्छी बात लगता है कि मुझे शब्दकोशों की एक सरणी के लिए किया जाएगा के लिए है, तो सरणी में 0 तत्व कुंजी के साथ एक शब्दकोश है "id" => "1"और "name" => "Aaa"

मुझे समझ नहीं आ रहा है कि कैसे NSJSONSerializationडेटा संग्रहीत करता है। यहाँ मेरा कोड अब तक है:

NSError *e = nil;
NSDictionary *JSON = [NSJSONSerialization 
    JSONObjectWithData: data 
    options: NSJSONReadingMutableContainers 
    error: &e];

यह सिर्फ एक चीज है जिसे मैंने एक अन्य वेबसाइट पर एक उदाहरण के रूप में देखा। मैं इस JSONतरह के तत्वों और चीजों की संख्या को प्रिंट करके ऑब्जेक्ट पर एक रीड प्राप्त करने की कोशिश कर रहा हूं, लेकिन मुझे हमेशा मिल रहा है EXC_BAD_ACCESS

मैं NSJSONSerializationऊपर दिए गए JSON को पार्स करने के लिए कैसे उपयोग कर सकता हूं और इसे मेरे द्वारा उल्लिखित डेटा संरचना में बदल सकता है?


आपका डेटा वैरिएबल शायद nil है
d.lebedev

ऐसा नहीं है, मैंने पहले ही परीक्षण कर लिया है।
लोगन सरमन

क्या आपने यह देखने की कोशिश की है कि क्या त्रुटि वस्तु में कोई प्रासंगिक जानकारी है?
मोनोलो

जवाबों:


214

आपकी रूट json ऑब्जेक्ट एक शब्दकोश नहीं है, लेकिन एक सरणी है:

[{"id": "1", "name":"Aaa"}, {"id": "2", "name":"Bbb"}]

यह आपको इसे कैसे संभालना है, इसकी स्पष्ट तस्वीर दे सकता है:

NSError *e = nil;
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData: data options: NSJSONReadingMutableContainers error: &e];

if (!jsonArray) {
  NSLog(@"Error parsing JSON: %@", e);
} else {
   for(NSDictionary *item in jsonArray) {
      NSLog(@"Item: %@", item);
   }
}

धन्यवाद मैं कोशिश करूँगा, लेकिन [JSON count]मुझे केवल EXC_BAD_ACCESS देने के बजाय कुछ वापस नहीं करना चाहिए ?
लोगन सरमन

यह होना चाहिए, यही कारण है कि मैंने चेक को जोड़ा !jsonArrayऔर यदि त्रुटि छपी। यह पार्स करने के दौरान हुई किसी भी त्रुटि को प्रदर्शित करना चाहिए।
rckoenes

1
@ xs2bush नहीं, चूंकि आपने इसे नहीं बनाया है इसलिए jsonArrayइसे ऑटोरेलिज होना चाहिए।
rckoenes

@ लोगन: हाँ, [JSON गणना] को एक मान लौटाना चाहिए। लाश के बारे में नीचे मेरा जवाब देखें। EXC_BAD_ACCESS लगभग हमेशा ज़ोंबी से संबंधित है।
ओली

इस स्थिति में, आइटम किसी दिए गए JSON कुंजी मूल्य जोड़ी में कुंजी है .. आपके लूप के लिए मेरी JSON कुंजी में से प्रत्येक को पूरी तरह से आउटपुट करने का काम करता है। हालाँकि मुझे पहले से ही मूल्य की कुंजी पता है, जो 'कुंजी' है। इस कुंजी का मान प्राप्त करने और इसे लॉग में आउटपुट करने के मेरे प्रयास विफल रहे हैं। कोई और जानकारी?
थॉमस क्लॉज

75

यह जाँचने के लिए मेरा कोड है कि क्या प्राप्त जसन एक सरणी या शब्दकोश है:

NSError *jsonError = nil;
id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&jsonError];

if ([jsonObject isKindOfClass:[NSArray class]]) {
    NSLog(@"its an array!");
    NSArray *jsonArray = (NSArray *)jsonObject;
    NSLog(@"jsonArray - %@",jsonArray);
}
else {
    NSLog(@"its probably a dictionary");
    NSDictionary *jsonDictionary = (NSDictionary *)jsonObject;
    NSLog(@"jsonDictionary - %@",jsonDictionary);
}

मैंने विकल्पों के लिए यह कोशिश की है: kNilOptions और NSJSONReadingMutableContainers और दोनों के लिए सही ढंग से काम करता है।

जाहिर है, वास्तविक कोड इस तरह से नहीं हो सकता है जहां मैं अगर-ब्लॉक के भीतर NSArray या NSDictionary सूचक बनाता हूं।


29

इससे मेरा काम बनता है। आपकी dataवस्तु संभवतः nilऔर है, जैसा कि नोट किया गया है, मूल वस्तु एक (परस्पर) सरणी होनी चाहिए। इस कोड को देखें:

NSString *jsonString = @"[{\"id\": \"1\", \"name\":\"Aaa\"}, {\"id\": \"2\", \"name\":\"Bbb\"}]";
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSError *e = nil;
NSMutableArray *json = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&e];
NSLog(@"%@", json);

(मुझे बैकस्लैश के साथ JSON स्ट्रिंग में उद्धरण से बचना था।)


9

आपका कोड ठीक लगता है सिवाय इसके कि परिणाम एक है NSArray, ए नहीं NSDictionary, यहाँ एक उदाहरण है:

पहली दो लाइनें सिर्फ JSON के साथ एक डेटा ऑब्जेक्ट बनाती हैं, जैसे ही आप इसे नेट से पढ़ते हैं।

NSString *jsonString = @"[{\"id\": \"1\", \"name\":\"Aaa\"}, {\"id\": \"2\", \"name\":\"Bbb\"}]";
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];

NSError *e;
NSMutableArray *jsonList = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&e];
NSLog(@"jsonList: %@", jsonList);

NSLog सामग्री (शब्दकोशों की सूची):

jsonList: (
           {
               id = 1;
               name = Aaa;
           },
           {
               id = 2;
               name = Bbb;
           }
           )

इस विकल्प (NSJSONReadingMutableContainers) का क्या अर्थ है। मैं kNilOption डॉन और सब कुछ ठीक काम करता है। मुझे इन विकल्प का उपयोग करने का उद्देश्य बताएं
ज़ार ई अहमर

Google में शीर्ष हिट NSJSONReadingMutableLeaves:: "निर्दिष्ट करता है कि JSON ऑब्जेक्ट ग्राफ में पत्ती के तार NSMutablebring के उदाहरण के रूप में बनाए गए हैं।"
11:55

और MutableContainer के बारे में क्या
ज़ार ई अहमर

ओह, फिर से शीर्ष Google परिणाम:: NSJSONReadingMutableContainers"निर्दिष्ट करता है कि सरणियों और शब्दकोशों को परस्पर वस्तुओं के रूप में बनाया गया है।"
ज़ाफ

1
यदि आप लौटे JSON ऑब्जेक्ट को संशोधित करने और इसे वापस सहेजने की योजना बनाते हैं तो ये केवल सहायता करते हैं। या तो मामले में, ऑब्जेक्ट शायद ऑटोरेल्ड ऑब्जेक्ट हैं और यह मूल कारण लगता है।
दीपक जीएम

6
[{"id": "1", "name":"Aaa"}, {"id": "2", "name":"Bbb"}]

JSON डेटा के ऊपर, आप दिखा रहे हैं कि हमारे पास शब्दकोशों की संख्या से संबंधित एक सरणी है।

आपको इसे पार्स करने के लिए इस कोड का उपयोग करने की आवश्यकता है:

NSError *e = nil;
NSArray *JSONarray = [NSJSONSerialization JSONObjectWithData: data options: NSJSONReadingMutableContainers error: &e];
        for(int i=0;i<[JSONarray count];i++)
        {
            NSLog(@"%@",[[JSONarray objectAtIndex:i]objectForKey:@"id"]);
             NSLog(@"%@",[[JSONarray objectAtIndex:i]objectForKey:@"name"]);
        }

स्विफ्ट 3/3 + के लिए

   //Pass The response data & get the Array
    let jsonData = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! [AnyObject]
    print(jsonData)
    // considering we are going to get array of dictionary from url

    for  item  in jsonData {
        let dictInfo = item as! [String:AnyObject]
        print(dictInfo["id"])
        print(dictInfo["name"])
    }

3

निम्न कोड एक वेबसर्वर से JSON ऑब्जेक्ट प्राप्त करता है, और इसे एक NS नॉडर पर भेजता है। मैंने Openweathermap API का उपयोग किया है जो इस उदाहरण के लिए एक साधारण JSON प्रतिक्रिया देता है। इसे सरल रखने के लिए, यह कोड सिंक्रोनस अनुरोधों का उपयोग करता है।

   NSString *urlString   = @"http://api.openweathermap.org/data/2.5/weather?q=London,uk"; // The Openweathermap JSON responder
   NSURL *url            = [[NSURL alloc]initWithString:urlString];
   NSURLRequest *request = [NSURLRequest requestWithURL:url];
   NSURLResponse *response;
   NSData *GETReply      = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
   NSDictionary *res     = [NSJSONSerialization JSONObjectWithData:GETReply options:NSJSONReadingMutableLeaves|| NSJSONReadingMutableContainers error:nil];
   Nslog(@"%@",res);

मुझे लगता है कि आपका उत्तर सबसे अच्छा उत्तर होना चाहिए क्योंकि यह JSON संरचना तक पहुंचने का सबसे तेज़ तरीका है।
पोरिज़्म

2
विकल्प दो का उपयोग नहीं करना चाहिए | लेकिन एक एकल | चूँकि उन्हें बिटवाइस ऑर्ड करने की आवश्यकता है।
दीपक जीएम

सवाल नेटवर्क अनुरोधों के बारे में कुछ नहीं पूछता है
नूह गिलमोर 20

2

@rckoenes ने आपको पहले ही दिखाया कि JSON स्ट्रिंग से अपने डेटा को सही तरीके से कैसे प्राप्त करें।

आपके द्वारा पूछे गए प्रश्न के लिए: EXC_BAD_ACCESSलगभग हमेशा तब आता है जब आप किसी ऑब्जेक्ट को एक्सेस करने की कोशिश करते हैं, जिसके बाद इसे [ऑटो-] जारी किया गया है। यह JSON [de-] क्रमांकन के लिए विशिष्ट नहीं है, बल्कि, बस आपको ऑब्जेक्ट प्राप्त करने और फिर इसे रिलीज़ होने के बाद एक्सेस करने के लिए करना होगा। तथ्य यह है कि यह JSON के माध्यम से आया था कोई फर्क नहीं पड़ता।

यह डीबग करने के तरीके का वर्णन करने वाले कई पृष्ठ हैं - आप Google (या SO) obj-c zombie objectsऔर विशेष रूप से चाहते हैं NSZombieEnabled, जो आपके ज़ोंबी ऑब्जेक्ट्स के स्रोत को निर्धारित करने में मदद करने में आपके लिए अमूल्य साबित होगा। ("ज़ोंबी" वह है जिसे आप किसी ऑब्जेक्ट को रिलीज़ करते समय कहते हैं लेकिन इसे एक पॉइंटर रखें और बाद में इसे संदर्भित करने का प्रयास करें।)


1

Xcode 7 (बीटा) पर स्विफ्ट 2.0 डू / ट्राई / कैच ब्लॉक के साथ:

// MARK: NSURLConnectionDataDelegate

func connectionDidFinishLoading(connection:NSURLConnection) {
  do {
    if let response:NSDictionary = try NSJSONSerialization.JSONObjectWithData(receivedData, options:NSJSONReadingOptions.MutableContainers) as? Dictionary<String, AnyObject> {
      print(response)
    } else {
      print("Failed...")
    }
  } catch let serializationError as NSError {
    print(serializationError)
  }
}

1

नोट: स्विफ्ट 3 के लिए । आपका JSON स्ट्रिंग, शब्दकोश के बजाय Array लौटा रहा है। कृपया निम्नलिखित प्रयास करें:

        //Your JSON String to be parsed
        let jsonString = "[{\"id\": \"1\", \"name\":\"Aaa\"}, {\"id\": \"2\", \"name\":\"Bbb\"}]";

        //Converting Json String to NSData
        let data = jsonString.data(using: .utf8)

        do {

            //Parsing data & get the Array
            let jsonData = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! [AnyObject]

            //Print the whole array object
            print(jsonData)

            //Get the first object of the Array
            let firstPerson = jsonData[0] as! [String:Any]

            //Looping the (key,value) of first object
            for (key, value) in firstPerson {
                //Print the (key,value)
                print("\(key) - \(value) ")
            }

        } catch let error as NSError {
            //Print the error
            print(error)
        }

0
#import "homeViewController.h"
#import "detailViewController.h"

@interface homeViewController ()

@end

@implementation homeViewController

- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.tableView.frame = CGRectMake(0, 20, 320, 548);
    self.title=@"Jason Assignment";

    // Uncomment the following line to preserve selection between presentations.
    // self.clearsSelectionOnViewWillAppear = NO;

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem;
    [self clientServerCommunication];
}

-(void)clientServerCommunication
{
    NSURL *url = [NSURL URLWithString:@"http://182.72.122.106/iphonetest/getTheData.php"];
    NSURLRequest *req = [NSURLRequest requestWithURL:url];
    NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:req delegate:self];
    if (connection)
    {
        webData = [[NSMutableData alloc]init];
    }
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    [webData setLength:0];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [webData appendData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:webData options:0 error:nil];

    /*Third party API
     NSString *respStr = [[NSString alloc]initWithData:webData encoding:NSUTF8StringEncoding];
     SBJsonParser *objSBJson = [[SBJsonParser alloc]init];
     NSDictionary *responseDict = [objSBJson objectWithString:respStr]; */
    resultArray = [[NSArray alloc]initWithArray:[responseDict valueForKey:@"result"]];
    NSLog(@"resultArray: %@",resultArray);
    [self.tableView reloadData];
}


- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
//#warning Potentially incomplete method implementation.
    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//#warning Incomplete method implementation.
    // Return the number of rows in the section.
    return [resultArray count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    }

    // Configure the cell...
    cell.textLabel.text = [[resultArray objectAtIndex:indexPath.row] valueForKey:@"name"];
    cell.detailTextLabel.text = [[resultArray objectAtIndex:indexPath.row] valueForKey:@"designation"];

    NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[resultArray objectAtIndex:indexPath.row] valueForKey:@"image"]]];
cell.imageview.image = [UIImage imageWithData:imageData];

    return cell;
}

/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Return NO if you do not want the specified item to be editable.
    return YES;
}
*/

/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the row from the data source
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }   
    else if (editingStyle == UITableViewCellEditingStyleInsert) {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
    }   
}
*/

/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/

/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Return NO if you do not want the item to be re-orderable.
    return YES;
}
*/


#pragma mark - Table view delegate

// In a xib-based application, navigation from a table can be handled in -tableView:didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Navigation logic may go here, for example:
     //Create the next view controller.
    detailViewController *detailViewController1 = [[detailViewController alloc]initWithNibName:@"detailViewController" bundle:nil];

 //detailViewController *detailViewController = [[detailViewController alloc] initWithNibName:@"detailViewController" bundle:nil];

 // Pass the selected object to the new view controller.

 // Push the view controller.
 detailViewController1.nextDict = [[NSDictionary alloc]initWithDictionary:[resultArray objectAtIndex:indexPath.row]];
 [self.navigationController pushViewController:detailViewController1 animated:YES];

    // Pass the selected object to the new view controller.

    // Push the view controller.
  //  [self.navigationController pushViewController:detailViewController animated:YES];
}



@end

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    empName.text=[nextDict valueForKey:@"name"];
    deptlbl.text=[nextDict valueForKey:@"department"];
    designationLbl.text=[nextDict valueForKey:@"designation"];
    idLbl.text=[nextDict valueForKey:@"id"];
    salaryLbl.text=[nextDict valueForKey:@"salary"];
    NSString *ImageURL = [nextDict valueForKey:@"image"];
    NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:ImageURL]];
    image.image = [UIImage imageWithData:imageData];
}

0

मुद्दा वस्तुओं के ऑटोरेलेज के साथ लगता है। NSJSONSerialization JSONObjectWithData स्पष्ट रूप से कुछ ऑटोरेल्ड ऑब्जेक्ट्स बना रहा है और इसे आपको वापस भेज रहा है। यदि आप इसे एक अलग धागे पर लेने की कोशिश करते हैं, तो यह काम नहीं करेगा क्योंकि यह एक अलग धागे पर नहीं लगाया जा सकता है।

ट्रिक उस शब्दकोश या सरणी की एक परिवर्तनशील प्रतिलिपि बनाने की कोशिश करने और उसका उपयोग करने के लिए हो सकती है।

NSError *e = nil;
id jsonObject = [NSJSONSerialization 
JSONObjectWithData: data 
options: NSJSONReadingMutableContainers 
error: &e] mutableCopy];

एनएसएयर्र के रूप में एक एनएसएड्रोड का इलाज करने से खराब एक्सेस अपवाद नहीं होगा, बल्कि एक विधि कॉल किए जाने पर संभवतः दुर्घटनाग्रस्त हो जाएगा।

इसके अलावा, विकल्प वास्तव में यहाँ मायने नहीं रखते हैं, लेकिन NSJSONReadingMutableContainers देना बेहतर है। NSJSONReadingMutableContainers | NSJSONReadingAllowFragments लेकिन अगर वे ऑटोरेल्ड ऑब्जेक्ट हैं तो भी यह समस्या हल नहीं हो सकती है।


दीपक, आपने NSJSONReadingMutableContainers को दो बार सूचीबद्ध किया। क्या आपका मतलब NSJSONReadingMutableLeaves होना चाहिए?
jk7

0

बुरा उदाहरण, कुछ इस तरह होना चाहिए {"आईडी": 1, "नाम": "नाम के रूप में कुछ"}

संख्या और स्ट्रिंग मिश्रित हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.