Как конвертировать JSON в объект

Я определил некоторые пользовательские классы, такие как Teacher, Student... Теперь я получаю информацию о преподавателях (строка JSON) с удаленного сервера.

Как преобразовать строку JSON в объект Teacher.

В Java легко реализовать общий метод для всего класса (Teacher, Student...) с помощью reflect.

Но в Objective-C на iOS лучший способ найти - использовать Entity Core Data, который имеет метод setValue:forKey. Сначала я преобразовываю строку JSON в NSDictionary, задает пару ключ-значение в направлении от Entry.

Есть ли лучшие способы?

(Я из Китая, поэтому, возможно, мой английский плохой, извините!)

Ответ 1

Это все хорошие рамки для JSON, анализирующие словари или другие примитивы, но если вы хотите избежать много повторяющейся работы, посмотрите http://restkit.org. В частности, проверьте https://github.com/RestKit/RestKit/blob/master/Docs/Object%20Mapping.md Это пример отображения объектов, в котором вы определяете сопоставление для своего класса Учителя, а json автоматически преобразуется в Учителя объект с помощью KVC. Если вы используете сетевые вызовы RestKit, процесс прозрачен и прост, но у меня уже были мои сетевые вызовы, и мне нужно было преобразовать текст ответа json в объект User (учитель в вашем случае), и я, наконец, понял как. Если это вам нужно, отправьте комментарий, и я расскажу, как это сделать с помощью RestKit.

Примечание. Я предполагаю, что json выводится с использованием сопоставленного соглашения {"teacher": { "id" : 45, "name" : "Teacher McTeacher"}}. Если это не так, но вместо этого, как этот {"id" : 45, "name" : "Teacher McTeacher"}, тогда не беспокойтесь... object mapping design doc в ссылке показывает вам, как это сделать... несколько дополнительных шагов, но не так уж плохо.

Это мой обратный вызов из ASIHTTPRequest

- (void)requestFinished:(ASIHTTPRequest *)request {
    id<RKParser> parser = [[RKParserRegistry sharedRegistry] parserForMIMEType:[request.responseHeaders valueForKey:@"Content-Type"]]; // i'm assuming your response Content-Type is application/json
    NSError *error;
    NSDictionary *parsedData = [parser objectFromString:apiResponse error:&error];
    if (parsedData == nil) {
        NSLog(@"ERROR parsing api response with RestKit...%@", error);
        return;
    }

    [RKObjectMapping addDefaultDateFormatterForString:@"yyyy-MM-dd'T'HH:mm:ssZ" inTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]]; // This is handy in case you return dates with different formats that aren't understood by the date parser

    RKObjectMappingProvider *provider = [RKObjectMappingProvider new];

    // This is the error mapping provider that RestKit understands natively (I copied this verbatim from the RestKit internals ... so just go with it
    // This also shows how to map without blocks
    RKObjectMapping* errorMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class]];
    [errorMapping mapKeyPath:@"" toAttribute:@"errorMessage"];
    [provider setMapping:errorMapping forKeyPath:@"error"];
    [provider setMapping:errorMapping forKeyPath:@"errors"];

    // This shows you how to map with blocks
    RKObjectMapping *teacherMapping = [RKObjectMapping mappingForClass:[Teacher class] block:^(RKObjectMapping *mapping) {
        [mapping mapKeyPath:@"id" toAttribute:@"objectId"];
        [mapping mapKeyPath:@"name" toAttribute:@"name"];
    }];

    [provider setMapping:teacherMapping forKeyPath:@"teacher"];

    RKObjectMapper *mapper = [RKObjectMapper mapperWithObject:parsedData mappingProvider:provider];
    Teacher *teacher = nil;
    RKObjectMappingResult *mappingResult = [mapper performMapping];
    teacher = [mappingResult asObject];

    NSLog(@"Teacher is %@ with id %lld and name %@", teacher, teacher.objectId, teacher.name);
}

Вы можете, очевидно, реорганизовать это, чтобы сделать его более чистым, но это теперь решает все мои проблемы.. больше не синтаксический анализ... просто ответ → magic → Object

Ответ 2

Во-первых, вы используете JSON Parser? (если нет, я бы рекомендовал использовать SBJson).

Во-вторых, почему бы не создать метод initWithDictionary init в вашем пользовательском классе, который возвращает самообъект?