2015-04-16 12 views
17

jestem pobierania danych JSON z adresu URL, który jest sformatowany tak:dane POST JSON do istniejącego obiektu

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

mam żadnej kontroli nad strukturą, jak to jest z prywatnej API.

Jak wstawić dane w wybranym polu danych istniejącego obiektu?

Próbowałem to:

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"); 
} 

Połączenie jest wykonane ale słownika params jest pusty po wydrukowaniu (the setValue nie wyświetla) i nie wkracza żadnych danych w polu wybiorę.

Sprawdziłem te linki, ale nic nie wyjaśnia, czy zostanie wstawiony do odpowiedniego pola i oznacza, że ​​utworzy nowy obiekt, a nie zaktualizuje istniejący.

How to update data on server db through json api?

How to send json data in the Http request using NSURLRequest

metody Delegowanie

//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; 
} 

Pierwsza metoda tu stwierdza, że ​​dane zostały odebrane z "dotarła danych (null)", nie ma błędu w związku jednak ostatnia metoda wypisuje komunikat o błędzie "Tekst JSON nie zaczął się od tablicy lub obiektu i opcji, aby nie zezwalać na fragmenty.", co jest zrozumiałe, ponieważ nie ma danych ani obiektów, które są wysyłane.

Jak wstawić dane do wybranego pola istniejącego obiektu?

+0

gdzie i jak można rozpocząć Conn ** **? Mam na myśli [conn start] –

+0

@VivekMolkar Mam to wewnątrz metody (IBAction) i zakładam, że łączy się autonomicznie w oparciu o moje metody zwrotu '- (void) połączenie: (NSURLConnection *) połączenie didReceiveData: (NSData *) dane' , '- (void) connection: (NSURLConnection *) connection didFailWithError: (NSError *) error' oraz' - (void) connectionDidFinishLoading: (NSURLConnection *) connection' –

+0

Nie, musisz wpisać linię kodu '[conn start ] ', aby zainicjować połączenie. ** conn ** sam się nie inicjuje. –

Odpowiedz

13

Robisz to źle:

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

Twój params jest pusty słownik i żaden obiekt zostanie zwrócony z [params objectForKey:@"zoneresponse"].

Spróbuj tego:

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

to będzie działać, ale obiekt za kluczowy @"tasks" będzie niezmienna. Aby dodać kolejne przedmioty do tasks słowniku musimy zrobić to zmienne:

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

lub

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

Następnie można dodać kolejne przedmioty do tasks:

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

myślę, że moja odpowiedź będzie przynieś trochę przejrzystości operacjom ze słownikami.

+0

Świetna odpowiedź, dzięki temu, że naprawdę pomogły ci oczyścić ... –

2

kontekst architektoniczny swoim podejściu do wysyłania danych JSON do bazy danych, serwery:

Używasz starej metody (od 03') złożenia żądania HTTP POST na zdobycie wspaniałych danych JSON w do baza danych serwerów. Jest to nadal funkcjonalne, a nie przestarzałe i ostatecznie dopuszczalne podejście. Zazwyczaj sposób działania tego podejścia polega na skonfigurowaniu i uruchomieniu polecenia NSURLRequest za pomocą połączenia NSURLConnection, obiekt ViewController lub obiekt, który wywołał żądanie, zwykle implementuje protokół NSURLConnection, dzięki czemu istnieje metoda wywołania zwrotnego, która odbiera odpowiedź związaną z NSURLRequests, tak jak to zrobiono. Dostępne są również opcje NSURLCaching i NSHTTPCookStorage, aby uniknąć nadmiarowości i przyspieszyć cały proces.

Jest nowa droga (od 13'):

NSURLConnections następca jest NSURLSession. Ponieważ odpowiedź Władimira Krawczenki skupia się na tworzeniu NSDictionary, który ma być wysłany jako parametr, który pokazał, że musisz użyć NSMutableDictionary zamiast statycznego NSDictionary, którego nie można edytować po jego uruchomieniu. Skoncentruję się na podejściu do tworzenia sieci wokół twojego pytania, aby być pomocnym.

/* 
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]; 

Dalsze Reading

Zawsze wspaniały Mattt Thompson napisał o przejściu z NSURLConnection do NSURLSession tutaj: objc.io

można znaleźć inny podobny pytania przepełnienie stosu tutaj: Stack Overflow

Jeśli chcesz mieć bibliotekę sieciową, która sprawia, że ​​te problemy są nieco łatwiejsze, sprawdź Mattt Thompsons AFNetworking wh Ich można znaleźć tutaj: GitHub

dalszej analizy na NSURLConnection kontra NSURLSession można znaleźć tutaj: Ray Wenderlich

+1

Naprawdę dokładna odpowiedź.Będę musiał spróbować i wdrożyć rzeczy jutro, ponieważ obecnie jestem poza biurem. Spojrzałem na AFNetworking, jednak dla wszystkich intensywnych celów nie pasowało to do tego, czego potrzebowałem w tym konkretnym przypadku, stąd pytanie. Pytanie dotyczące stosu w rzeczywistości nie obejmuje dokładnie tego pytania, ale dostarcza pewnych dobrych stron dotyczących połączenia. Dziękuję za odpowiedź. Na pewno spróbuję zrealizować jutro. –