如何将JSON数据发布到现有对象中?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (73)

我从格式如下的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未显示),并且未将任何数据输入到我选择的字段中。

我已经检查了这些链接,但没有任何解释它是否会插入到正确的字段中,并暗示它将创建一个新对象而不是更新现有对象。

委托方法

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

这里的第一种方法表明数据是在“接收数据(空)”的情况下收到的,连接没有错误,但最终的方法打印错误消息“JSON文本没有以数组或对象开始,选项允许片段未设置“,这是可以理解的,因为没有数据或对象被发送。

如何将数据插入到现有对象的选定字段中?

提问于
用户回答回答于

你做错了:

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";
用户回答回答于

将JSON数据发送到服务器数据库的方法的架构上下文:

正在使用一种旧方法(自03'以来)发出HTTP POST请求,以将可爱的JSON数据存入服务器数据库。它仍然有效并且不被弃用,并且最终是可接受的方法。通常情况下,这种方法是如何工作的,你设置并使用NSURLConnection触发NSURLRequest,触发请求的ViewController或对象通常会实现NSURLConnection协议,所以你有一个回调方法,像你一样接收NSURLRequests相关的响应。Theres还有一些NSURLCaching和NSHTTPCookStorage可用来避免冗余并加速整个事情。

有一种新的方式(自13'以来):

NSURLConnections后继是NSURLSession。它表明需要使用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

如果你想要一个网络库,使这些问题更容易检查Mattt Thompsons AFNetworking,可以在这里找到: GitHub

关于NSURLConnection与NSURLSession的进一步分析可以在这里找到:Ray Wenderlich

扫码关注云+社区