2012-04-24 11 views
7

Estoy construyendo una aplicación de sincronización de Dropbox bidireccional. Cargué objetos de datos centrales, los convierto en JSON y los envío a Dropbox. Sin embargo, cuando sincronizo, comparo un conjunto de archivos JSON locales con los archivos JSON de Dropbox. Si se detecta un conflicto, se aplica una lógica de sincronización. Como resultado de la lógica de sincronización, se puede descargar un archivo JSON remoto y reemplazará el archivo JSON local.iPhone RestKit cómo cargar un archivo JSON local y asignarlo a una entidad de datos central?

Así que termino con un montón de archivos JSON en un directorio de documentos locales.

¿Cómo puedo utilizar RestKit para deserializar los archivos JSON locales de nuevo en objetos utilizando asignaciones que he definido? El RKTwitterCoreData crea una entidad de datos central a partir de un JSON basado en web. Estoy tratando de hacer lo mismo con un archivo JSON local.

Hay un montón de métodos loadObjects, pero todos ellos parecen funcionar con llamadas web:

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

Gracias!

+0

¿Ha intentado pasar una ruta de acceso local al método loadObjectsAtResourcePath? – shannoga

Respuesta

0

Esto es lo que estoy usando para convertir Core Data a JSON en 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); 
    } 

} 

A continuación se explica cómo definir un modelo de objeto RestKit anidado. Cuando se deserializa un archivo JSON de esta estructura, creará automáticamente todas las relaciones anidadas e incluso combinará contextos de objetos gestionados.

+(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]]; 


} 
6

Se trata de los documentos del Resto-Kit, no lo he probado todavía, pero parece que el comienzo, ya que utilizan una cadena JSON.

Se puede encontrar aquí: look at the bottom of the page

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 
} 

EDITAR ver nota rob5408 sobre salvar el contexto:

[[RKObjectManager sharedManager].objectStore.managedObjectContext save:&error]; 
+0

Funcionó muy bien. ¡Gracias! – jcanfield55

+1

Gracias @shannoga, esto fue súper útil. Me gustaría señalar que tuve que guardar el contexto de Core Data luego para que los objetos persistieran. [[RKObjectManager sharedManager] .objectStore.managedObjectContext save: & error]; – rob5408

+0

Genial, gracias @ rob5408 por su nota que se agregó a la respuesta – shannoga

1

Si usted quiere tener el mismo comportamiento exacto como el " Por defecto "Restkit función - (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects puede usar eso para obtener el precioso objects NSArray:

RKObjectMappingResult* result = [mapper performMapping]; 
NSArray* objects = [result asCollection]; 
Cuestiones relacionadas