iPhone RestKit, как загрузить локальный файл JSON и сопоставить его с основным объектом данных?

Я создаю приложение для двусторонней синхронизации Dropbox. Я загружаю объекты из основных данных, конвертирую их в JSON и отправляю в дропбокс. Однако при синхронизации я сравниваю набор локальных файлов JSON с файлами JSON в раскрывающемся списке. При обнаружении конфликта применяется логика синхронизации. В результате логики синхронизации удаленный файл JSON может быть загружен и заменит локальный файл JSON.

Итак, я получаю кучу файлов JSON в локальном каталоге документов.

Как я могу использовать RestKit для десериализации локальных файлов JSON обратно в объекты, используя определенные мной сопоставления? RKTwitterCoreData создает основной объект данных из веб-JSON. Я пытаюсь сделать то же самое с локальным файлом JSON.

Существует множество методов loadObjects, но все они работают с веб-вызовами:

- (RKObjectLoader*)loadObjectsAtResourcePath:(NSString*)resourcePath delegate:(id<RKObjectLoaderDelegate>)delegate;

Спасибо !


person Alex Stone    schedule 24.04.2012    source источник
comment
Вы пытались передать локальный путь методу loadObjectsAtResourcePath?   -  person shannoga    schedule 21.05.2012


Ответы (3)


Это из документов Rest-Kit, еще не пробовал, но похоже на начало, поскольку они используют строку JSON.

Вы можете найти его здесь: смотрите внизу страницы

NSString* JSONString = @"{ \"name\": \"The name\", \"number\": 12345}";
NSString* MIMEType = @"application/json";
NSError* error = nil;
id<RKParser> parser = [[RKParserRegistry sharedRegistry] parserForMIMEType:MIMEType];
id parsedData = [parser objectFromString:JSONString error:&error];
if (parsedData == nil && error) {
    // Parser error...
}


RKObjectMappingProvider* mappingProvider = [RKObjectManager sharedManager].mappingProvider;
RKObjectMapper* mapper = [RKObjectMapper mapperWithObject:parsedData mappingProvider:mappingProvider];
RKObjectMappingResult* result = [mapper performMapping];
if (result) {
    // Yay! Mapping finished successfully
}

ИЗМЕНИТЬ см. примечание rob5408 о сохранении контекста:

 [[RKObjectManager sharedManager].objectStore.managedObjectContext save:&error];
person shannoga    schedule 21.05.2012
comment
Спасибо @shannoga, это было очень полезно. Я хотел бы отметить, что впоследствии мне пришлось сохранить контекст основных данных, чтобы объекты сохранялись. [[RKObjectManager sharedManager].objectStore.managedObjectContext save:&error]; - person rob5408; 11.10.2012

Если вы хотите иметь то же самое поведение, что и функция Restkit «по умолчанию» - (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects, вы можете использовать ее для получения драгоценного objects NSArray :

RKObjectMappingResult* result = [mapper performMapping];
NSArray* objects = [result asCollection];
person adriendenat    schedule 03.10.2012

Вот что я использую для преобразования Core Data в JSON в Core Data.

  -(void)deserializeFileAtPath:(NSString*)filePath
{
    DLog(@"Deserialize file: %@",filePath);
    NSError* error = nil;
    NSString *stringJSON = [NSString stringWithContentsOfFile:filePath usedEncoding:nil error:&error];
    if(error)
    {
        NSLog(@"Error reading from file: %@", filePath);
    }

    //restore the dictionary, as it was serialized
    NSDictionary* serializationDictionary =  [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:filePath] options:NSJSONReadingMutableContainers error:&error];

    //Here you must ensure that your object mapping exists
    [CoreDataWrapper setupCoreDataObjectMapping];

//top level object within JSON it will have one entity that you really want to deserialize. Without a wrapper, the mapper would not know what the top level entity really is
    CoreDataWrapper* wrapper = [CoreDataWrapper object];

    RKObjectMapper* mapper;
    error = nil;

//this performs deserialization. if you get errors about designated initializer not being called, you have setup a wrong object mapping. You need to define RKManagedObjectMapping for your core data classes
    mapper = [RKObjectMapper mapperWithObject:serializationDictionary 
                              mappingProvider:[RKObjectManager sharedManager].mappingProvider];
    RKObjectMappingResult* result = [mapper performMapping];

    //top level object within wrapper that holds the real payload
    RealCoreDataEntity* realCoreData = [result asObject];
    realCoreData.wrapper = wrapper;

//just in case
    [[wrapper managedObjectContext]save:nil];

//prints what we got back
    DLog(@"%@", realCoreData);

//prints any nested relationships
    for(NestedRelationshipObject* relationshipEntity in realCoreData.relationship)
    {
        DLog(@"Nested entity:%@", relationshipEntity);
    }

}

Вот как определить вложенную объектную модель RestKit. Когда файл JSON этой структуры десериализуется, он автоматически создаст для вас все вложенные отношения и даже объединит контексты управляемых объектов!

+(void)setupCoreDataObjectMapping
{

RKObjectManager *objectManager = [RKObjectManager sharedManager ] ;

// Setup our object mappings    
/*!
 Mapping by entity. Here we are configuring a mapping by targetting a Core Data entity with a specific
 name. This allows us to map back Twitter user objects directly onto NSManagedObject instances --
 there is no backing model class!
 */
//********************************    
RKManagedObjectMapping* nestedRelationshipMapping = [RKManagedObjectMapping mappingForEntityWithName:@"NestedRelationshipObject"];
//UUID determines which objects get updated and which ones get created during the mapping process
nestedRelationshipMapping.primaryKeyAttribute = @"uuid";
[nestedRelationshipMapping mapKeyPathsToAttributes:
 @"IKeepTheseTheSame", @"IKeepTheseTheSame",
 @"AnotherValue",@"AnotherValue",
 //keep adding your attributes
 nil];
[objectManager.mappingProvider addObjectMapping:nestedRelationshipMapping];




//********************************    

RKManagedObjectMapping* mainPayloadMapping = [RKManagedObjectMapping mappingForEntityWithName:@"RealCoreDataEntity"];
mainPayloadMapping.primaryKeyAttribute = @"uuid";
[mainPayloadMapping mapKeyPathsToAttributes:
 @"companyName",@"companyName",
 //keep adding your attributes
 nil];


//this is the main payload. I create all of it's relationships before, and then add them to the mapping.
[mainPayloadMapping mapRelationship:@"relationshipName" withMapping:nestedRelationshipMapping];
[objectManager.mappingProvider addObjectMapping:mainPayloadMapping];


[objectManager.mappingProvider setSerializationMapping:[mainPayloadMapping inverseMapping] forClass:[YourNSManagedObjectSubclass class]];


[objectManager.mappingProvider setMapping:nestedRelationshipMapping forKeyPath:@"mainPayloadToNestedDataRelationshipName"];
[objectManager.mappingProvider setMapping:mainPayloadMapping forKeyPath:@"wrapperToMainPayloadRelationshipName"];


//this is a top level JSON object. It's name will not be identified within the object, but it's relationshipName will be. The result of deserializing this object would be an object that is being wrapped.
RKManagedObjectMapping* wrapperMapping = [RKManagedObjectMapping mappingForClass:[IconFileWrapper class]];
iconWrapperMapping.primaryKeyAttribute = @"uuid";
//    keyPath and attribute names. must be even
[iconWrapperMapping mapKeyPathsToAttributes:@"uuid",@"uuid",nil];
//keep adding your attributes
[iconWrapperMapping mapRelationship:@"relationshipName" withMapping:mainPayloadMapping];

[objectManager.mappingProvider addObjectMapping:wrapperMapping];
[objectManager.mappingProvider setSerializationMapping:[wrapperMapping inverseMapping] forClass:[YourWrapperNSManagedObjectSubclass class]];


}
person Alex Stone    schedule 21.05.2012