我从一个URL中检索JSON数据,该URL的格式如下:
{"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 text not start with array or object and option to allow fragments not set.",这是可以理解的,因为没有发送数据或对象。
如何将数据插入现有对象的选定字段?
发布于 2015-04-22 17:47:59
您这样做是错误的:
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";
我认为我的答案会给你的字典操作带来一些清晰的东西。
发布于 2015-04-27 18:46:47
将数据发送到服务器数据库的方法的JSON体系结构上下文:
您正在使用一种旧方法(从03‘年开始)发出HTTP POST请求,将可爱的JSON数据放入服务器数据库。它仍然是有效的,没有被弃用,最终是一种可以接受的方法。通常,这种方法的工作原理是使用NSURLConnection设置和触发NSURLRequest,触发请求的ViewController或对象通常实现NSURLConnection协议,因此您有一个回调方法,它接收与NSURLRequests相关的响应。还有一些NSURLCaching和NSHTTPCookStorage可用来避免冗余并加快整个过程。
有一种新的方式(从13‘年开始):
NSURLConnections的后继者是NSURLSession。由于Vladimir Kravchenko的回答侧重于形成要作为参数发送的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];
进一步阅读
一直很棒的Mattt Thompson在这里写了关于从NSURLConnection到NSURLSession的过渡:objc.io
你可以在这里找到另一个类似的堆栈溢出问题:Stack Overflow
如果您想要一个使这些问题更简单的网络库,请查看Mattt Thompsons,它可以在以下位置找到:GitHub
有关NSURLConnection与NSURLSession的进一步分析可在此处找到:Ray Wenderlich
https://stackoverflow.com/questions/29669296
复制相似问题