我正在从格式如下的URL中检索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未显示),并且未在我选择的字段中输入任何数据。
我已经检查了这些链接,但没有解释它是否会插入到正确的字段中并暗示它将创建一个新对象而不是更新现有对象。
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;
}
这里的第一个方法声明数据是通过“Did Receive data(null)”接收的,连接没有错误,但是最终方法打印错误消息“JSON文本没有以数组或对象开始,并且允许选项片段未设置。“,这是可以理解的,因为没有数据或对象被发送。
如何将数据插入现有对象的选定字段?
答案 0 :(得分: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";
我认为我的回答会为你的字典操作带来一些清晰度。
答案 1 :(得分:2)
将JSON数据发送到服务器数据库的方法的架构上下文:
您正在使用一种旧方法(自03')发出HTTP POST请求以将您可爱的JSON数据输入到服务器数据库中。它仍然是功能性的,不会被弃用,最终是一种可接受的方法。通常,这种方法的工作方式是使用NSURLConnection设置和触发NSURLRequest,触发请求的ViewController或对象通常实现NSURLConnection协议,因此您有一个回调方法,可以在您完成时接收NSURLRequests相关响应。还有一些NSURLCaching和NSHTTPCookStorage可用于避免冗余并加速整个事情。
有一种新方法(自13'):
NSURLConnections继任者是NSURLSession。由于Vladimir Kravchenko的回答集中于将NSDictionary作为参数发送,该参数表明您需要使用NSMutableDictionary而不是静态NSDictionary,这些NSDictionary在其初始化之后无法编辑&#39 ;编尽管为了提供帮助,我将专注于围绕您的问题的网络方法。
/*
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];
进一步阅读
总是很棒的Mattt Thompson在这里写到了从NSURLConnection到NSURLSession的过渡:objc.io
您可以在此处找到另一个类似的Stack Overflow问题:Stack Overflow
如果您想要一个能够轻松解决这些问题的网络库,请查看Mattt Thompsons AFNetworking,可在此处找到: GitHub
可以在此处找到有关NSURLConnection与NSURLSession的进一步分析:Ray Wenderlich