2015-04-16 65 views
17

我從被格式化,像這樣一個URL獲取JSON數據:POST JSON數據到現有的對象

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

我在結構上沒有控制,因爲它是從私有API。

如何在現有對象的選定數據字段中插入數據?

我曾嘗試這樣的:

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

該連接正被提出,但在打印時(所述的setValue沒有顯示),並且不輸入任何數據到我選擇字段字典params爲空。

我檢查了這些鏈接,但沒有任何解釋它是否會插入到正確的字段中,並暗示它將創建新對象而不是更新現有對象。

How to update data on server db through json api?

How to send json data in the Http request using NSURLRequest

委託方法

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

這裏的第一個方法,指出數據與「的確收到數據(空)」收到,有但是與連接沒有錯誤final方法打印錯誤消息「JSON文本沒有以數組或對象開始,選項允許片段未設置」,這是可以理解的,因爲沒有數據或對象被髮送。

如何將數據插入到現有對象的選定字段中?

+0

在哪裏以及你如何啓動** **康涅狄格州?我的意思是[conn start] –

+0

@VivekMolkar我有一個(IBAction)方法的內部,我假設它根據我的返回方法自動連接 - (void)連接:(NSURLConnection *)連接didReceiveData:(NSData *)data' (NSURLConnection *)連接didFailWithError:(NSError *)error'和' - (void)connectionDidFinishLoading:(NSURLConnection *)connection' –

+0

不,您必須將一行代碼'[conn start ]'啓動連接。 ** conn **本身不會啓動。 –

回答

13

你這樣做不對:

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

params是空的字典,沒有對象將[params objectForKey:@"zoneresponse"]返回。

試試這個:

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

這會工作,但對象鍵@"tasks"將是不可改變的。要將其他對象添加到tasks字典,我們需要使其變更:

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

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

然後你就可以在其他對象添加到tasks

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

我認爲我的答覆爲您的字典操作帶來一些清晰。

+0

很好的答案,謝謝你的幫助。真的有助於清理問題。 –

2

你的方法的建築文脈,以JSON數據發送到服務器的數據庫:製作一個HTTP POST請求來獲取到你可愛的JSON數據

您使用的是舊法(03' )服務器數據庫它仍然有效並且不被棄用,並且最終是可接受的方法。通常情況下,這種方法是如何工作的,你設置並使用NSURLConnection觸發NSURLRequest,觸發請求的ViewController或對象通常會實現NSURLConnection協議,所以你有一個回調方法,像你一樣接收NSURLRequests相關的響應。 Theres還有一些NSURLCaching和NSHTTPCookStorage可用來避免冗餘並加速整個事情。

有一種新的方式(自13' ):

NSURLConnections繼任者是NSURLSession。由於弗拉基米爾克拉夫琴科的回答集中在形成NSDictionary作爲參數發送,它表明您需要使用NSMutableDictionary而不是靜態NSDictionary,它在初始化後無法編輯。我將專注於圍繞您的問題的網絡方法,以便提供幫助。

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

進一步閱讀

的總是美好的馬特·湯普森已經撰寫了有關從NSURLConnection的到NSURLSession過渡位置:objc.io

你可以在這裏找到另一個類似的堆棧溢出問題:Stack Overflow

如果你想要一個網絡庫,使這些問題更容易檢查Mattt Thompsons AFNetworking wh ICH可以在這裏找到: GitHub

進一步分析NSURLConnection的對比NSURLSession可以在這裏找到:Ray Wenderlich

+1

真正徹底的答案。由於我目前離開辦公桌,我將不得不在明天嘗試實施。我看了AFNetworking,然而對於所有密集的目的來說,它並不適合我在這個特定情況下需要的東西,因此提出了這個問題。堆棧問題並沒有真正涵蓋這個問題,但它確實提供了關於連接的一些好的方面。感謝你的回答。我一定會嘗試明天實施。 –

相關問題