Подтвердить что ты не робот

Данные POST JSON в существующий объект

Я извлекаю данные 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 не отображается) и не вводит никаких данных в поле, которое я выбираю.

Я проверил эти ссылки, но ничего не объясняет, будет ли он вставляться в правильное поле и подразумевает, что он создаст новый объект, а не обновит существующий.

Как обновить данные на сервере db через json api?

Как отправить данные json в запрос Http с использованием 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;
}

В первом методе здесь говорится, что данные были получены с помощью "Получены данные приема (null)", нет никакой ошибки при подключении, однако последний метод печатает сообщение об ошибке "Текст JSON не запускался с массивом или объектом, а опция разрешить фрагменты не установлены.", что понятно, потому что нет данных или отправляемых объектов.

Как вставить данные в выбранное поле существующего объекта?

4b9b3361

Ответ 1

Вы делаете это неправильно:

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

Я думаю, что мой ответ принесет определенную ясность в операции со словарями для вас.

Ответ 2

Архитектурный контекст вашего подхода к отправке данных JSON в базу данных серверов:

Вы используете старый метод (начиная с 03 ') запроса HTTP POST, чтобы получить ваши прекрасные данные JSON в базу данных серверов. Он по-прежнему является функциональным, а не устаревшим и, в конечном итоге, приемлемым подходом. Обычно, как работает этот подход, вы настраиваете и запускаете NSURLRequest с NSURLConnection, ViewController или объект, который запускал запрос, как правило, реализует протокол NSURLConnection, поэтому у вас есть метод обратного вызова, который получает ответ, связанный с NSURLRequests, как вы это делали. Также доступны некоторые 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 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 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

Здесь вы можете найти другие подобные вопросы: Переполнение стека

Если вы хотите создать сетевую библиотеку, которая упростит эти проблемы, попробуйте найти MattT Thompsons AFNetworking, который можно найти здесь: GitHub

Дальнейший анализ NSURLConnection по сравнению с NSURLSession можно найти здесь: Ray Wenderlich