2015-04-16 7 views
17

I JSON-Daten von einer URL ist abgerufen werden, wie so formatiert ist:POST JSON-Daten in Objekt bestehenden

{"zoneresponse": 
{"tasks": 
[{"datafield1":"datafor1", 
    "datafield2":"datafor2", 
    "datafield3":"datafor3",... 
}] 
}} 

Ich habe keine Kontrolle über die Struktur, wie sie von einem privaten API sind.

Wie füge ich Daten in ein ausgewähltes Datenfeld eines vorhandenen Objekts ein?

Ich habe dies versucht:

self.responseData = [NSMutableData data]; 

//testingURL is the api address to the specific object in tasks 
NSURL *url = [NSURL URLWithString:testingURL]; 

NSMutableDictionary *params = [[NSMutableDictionary alloc] init]; 
[[[params objectForKey:@"zoneresponse"] objectForKey:@"tasks"] setValue:@"HelloWorld" forKey:@"datafield1"]; 
//HAVE TRIED setObject: @"" objectForKey: @"" as well 

//*****PARAMS IS EMPTY WHEN PRINTED IN NSLog WHICH IS PART OF THE ISSUE - SETTING VALUE DOES NOT WORK 

NSError * error = nil; 

NSLog(@"Params is %@", params); 

NSData *requestdata = [NSJSONSerialization dataWithJSONObject:params options:0 error:&error]; 

NSMutableURLRequest *request; 
request = [NSMutableURLRequest requestWithURL:url]; 
[request setHTTPMethod:@"POST"]; 
[request setValue:[NSString stringWithFormat:@"%d", [requestdata length]] forHTTPHeaderField:@"Content-Length"]; 
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"]; 
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; 
[request setHTTPBody:requestdata]; 

NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self]; 


if(conn) { 
    NSLog(@"Connection Successful, connection is: %@", conn); 

} else { 
    NSLog(@"Connection could not be made"); 
} 

die Verbindung hergestellt wird, aber die Wörterbuch params ist leer, wenn sie gedruckt (die setValue wird nicht angezeigt), und wird die Eingabe keine Daten in den Bereich I auszuwählen.

Ich habe diese Links überprüft, aber nichts erklärt, ob es in das richtige Feld eingefügt wird und impliziert, dass es ein neues Objekt erstellen wird, anstatt das vorhandene zu aktualisieren.

How to update data on server db through json api?

How to send json data in the Http request using NSURLRequest

Delegatmethoden

//any time a piece of data is received we will append it to the responseData object 
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
{ 
    [self.responseData appendData:data]; 

    NSError *jsonError; 

    id responseDict = 
    [NSJSONSerialization JSONObjectWithData:self.responseData 
           options:NSJSONReadingAllowFragments 
            error:&jsonError]; 

    NSLog(@"Did Receive data %@", responseDict); 
} 

//if there is some sort of error, you can print the error or put in some other handling here, possibly even try again but you will risk an infinite loop then unless you impose some sort of limit 
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
{ 
    // Clear the activeDownload property to allow later attempts 
    self.responseData = nil; 

    NSLog(@"Did NOT receive data "); 

} 

//connection has finished, the requestData object should contain the entirety of the response at this point 
- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
{ 
    NSError *jsonError; 
    id responseDict = 
    [NSJSONSerialization JSONObjectWithData:self.responseData 
           options:NSJSONReadingAllowFragments 
            error:&jsonError]; 
    if(responseDict) 
    { 
     NSLog(@"%@", responseDict); 
    } 
    else 
    { 
     NSLog(@"%@", [jsonError description]); 
    } 

    //clear out our response buffer for future requests 
    self.responseData = nil; 
} 

Die erste Methode hier heißt es, dass Daten mit "Erhielten Daten (null)" empfangen wurde, ist kein Fehler mit Verbindung jedoch die Die finale Methode gibt die Fehlermeldung "JSON-Text startet nicht mit Array oder Objekt und Option, um nicht gesetzte Fragmente zuzulassen" aus, was verständlich ist, da keine Daten oder Objekte gesendet werden.

Wie füge ich Daten in ein ausgewähltes Feld eines vorhandenen Objekts ein?

+0

, wo und wie soll man anfangen den ** conn **? Ich meine [conn Start] –

+0

@VivekMolkar Ich habe dies innerhalb einer (IBAction) -Methode und ich nehme an, es verbindet sich autonom auf der Grundlage meiner Rückkehr Methoden '- (void) Verbindung: (NSURLConnection *) Verbindung didReceiveData: (NSData *) data' , '- (void) Verbindung: (NSURLConnection *) Verbindung didFailWithError: (NSError *) error' und' - (void) connectionDidFinishLoading: (NSURLConnection *) Verbindung' –

+0

Nein, Sie müssen eine Codezeile setzen '[conn start ] 'um die Verbindung herzustellen. ** conn ** allein nicht initiiert. –

Antwort

13

Sie tun dies falsch:

NSMutableDictionary *params = [[NSMutableDictionary alloc] init]; 
[[[params objectForKey:@"zoneresponse"] objectForKey:@"tasks"] setValue:@"HelloWorld" forKey:@"datafield1"]; 

Ihr params ist leer Wörterbuch und kein Objekt wird mit [params objectForKey:@"zoneresponse"] zurückgegeben werden.

Versuchen Sie folgendes:

NSMutableDictionary *params = [NSMutableDictionary new]; 
params[@"zoneresponse"] = @{@"tasks": @{@"datafield1": @"HelloWorld"}}; 

Dies funktioniert aber Objekt für Schlüssel @"tasks" wird unveränderlich sein. Um weitere Objekte zu tasks Wörterbuch hinzufügen müssen wir es wandelbar machen:

NSMutableDictionary *params = [NSMutableDictionary new]; 
NSMutableDictionary *tasks = [NSMutableDictionary new]; 
params[@"zoneresponse"] = @{@"tasks": tasks}; 
params[@"zoneresponse"][@"tasks"][@"datafield1"] = @"HelloWorld"; 

oder

NSMutableDictionary *params = [NSMutableDictionary new];  
params[@"zoneresponse"] = @{@"tasks": [@{@"datafield1": @"HelloWorld"} mutableCopy]}; 

Dann können Sie weitere Objekte tasks hinzufügen:

params[@"zoneresponse"][@"tasks"][@"datafield2"] = @"HelloWorld2"; 
params[@"zoneresponse"][@"tasks"][@"datafield3"] = @"HelloWorld3"; 

Ich denke, meine Antwort wird bringen Sie Klarheit in den Betrieb mit Wörterbüchern für Sie.

+0

Große Antwort danke Haufen dafür. Wirklich geholfen, die Dinge zu klären. –

2

Architektur Kontext Ihres Ansatz JSON-Daten an eine Server-Datenbank zu senden:

Sie verwenden eine alte Methode (seit 03'), die eine HTTP-POST-Anfrage macht Ihre schöne JSON-Daten, um die bekommen Server-Datenbank. Es ist immer noch funktional und nicht veraltet und letztlich ein akzeptabler Ansatz. In der Regel funktioniert die Vorgehensweise wie folgt: Sie richten einen NSURLRequest mit einer NSURLConnection ein, und der ViewController oder das Objekt, das die Anforderung ausgelöst hat, implementiert normalerweise das NSURLConnection-Protokoll, sodass Sie eine Rückrufmethode haben, die die NSURLRequests-zugeordnete Antwort empfängt. Theres auch einige NSURLCaching und NSHTTPCookStorage zur Verfügung, um Redundanz zu vermeiden und die ganze Sache zu beschleunigen.

Es gibt eine neue Art und Weise (seit 13'):

NSURLConnections Nachfolger ist NSURLSession. Da sich Vladimir Kravchenkos Antwort darauf konzentriert, das NSDictionary als einen Parameter zu erstellen, der gezeigt hat, dass Sie ein NSMutableDictionary anstelle eines statischen NSDictionary verwenden müssen, das nicht bearbeitet werden kann, nachdem es init'ed ist. Ich werde mich jedoch auf den Netzwerkansatz konzentrieren, der Ihre Frage umgibt, um hilfreich zu sein.

/* 
The advantage of this code is it doesn't require implementing a 
protocol or multiple callbacks. 
It's self contained, uses a more modern framework, less code 
and can be just thrown in to the viewDidAppear 

Basically - theres less faffing about while being a little easier to understand. 
*/ 
NSError *requestError; 
// session config 
NSURLSessionConfiguration *configuration = 
[NSURLSessionConfiguration defaultSessionConfiguration]; 
NSURLSession *session = 
[NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil]; 
// setup request 
NSURL *url = [NSURL URLWithString:testingURL]; 
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url 
                 cachePolicy:NSURLRequestUseProtocolCachePolicy 
                timeoutInterval:60.0]; 

[request addValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; 
[request addValue:@"application/json" forHTTPHeaderField:@"Accept"]; 
[request setHTTPMethod:@"POST"]; 
// setup request parameters, Vladimir Kravchenko's use of literals seems fine and I've taken his code 
NSDictionary *params = @{@"zoneresponse" : @{@"tasks" : [@{@"datafield1" : @"HelloWorld"} mutableCopy]}}; 
params[@"zoneresponse"][@"tasks"][@"datafield2"] = @"HelloWorld2"; 
params[@"zoneresponse"][@"tasks"][@"datafield3"] = @"HelloWorld3"; 
// encode parameters 
NSData *postData = [NSJSONSerialization dataWithJSONObject:params options:0 error:&requestError]; 
[request setHTTPBody:postData]; 
// fire request and handle response 
NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler: 
    ^(NSData *data, NSURLResponse *response, NSError *error) 
{ 
    NSError *responseError; 
    // parse response 
    NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:data 
                   options:NSJSONReadingAllowFragments 
                    error:&responseError]; 
    // handle response data 
    if (responseError){ 
     NSLog(@"Error %@", responseError) 
    }else{ 
     if (responseDict){ 
      NSLog(@"Response %@", responseDict); 
     } 
    } 
}]; 

[postDataTask resume]; 

Weiterführende Literatur

Die immer wunderbar Mattt Thompson über den Übergang von NSURLConnection zu NSURLSession hier geschrieben hat: objc.io

können Sie eine weitere ähnliche Stack Overflow Fragen finden Sie hier: Stack Overflow

Wenn Sie eine Netzwerk-Bibliothek möchten, die diese Probleme ein wenig einfacher macht, dann schauen Sie sich MattThompsons AFNetworking wh an ich kann hier gefunden werden: GitHub

Weitere Analysen auf NSURLConnection gegen NSURLSession hier gefunden werden kann: Ray Wenderlich

+1

Wirklich gründliche Antwort.Ich werde morgen versuchen müssen, Dinge umzusetzen, da ich gerade nicht am Schreibtisch bin. Ich habe mir AFNetworking angesehen, aber für alle intensiven Zwecke passte es nicht zu dem, was ich in diesem speziellen Fall brauchte, und stellte daher die Frage. Die Stack-Frage deckt die Frage nicht wirklich ab, bietet jedoch einige gute Punkte in Bezug auf die Verbindung. Danke für die Antwort. Ich werde sicher versuchen, morgen umzusetzen. –

Verwandte Themen