RestKit: ¿Cómo se publica una matriz de objetos?

Resumen de la pregunta:

Considere un SyncObject clase que sea compatible con KVC con propiedades tales como: time , someValue , lastChange , lastChange .

Considere un NSArray contiene exclusivamente instancias de SyncObject .

Necesito enviar la matriz al servidor como una matriz JSON.

¿Cómo se podría enviar esta matriz al servidor usando HTTP POST usando RestKit?

Ejemplo de matriz:

 [ { "time": "14:45 10/21/2011", "someValue": "15", "lastChange": "14:45 10/21/2011", "uuid": "0b07c510-f4c8-11e0-be50-0800200c9a66" }, { "time": "14:50 10/21/2011", "someValue": "62", "lastChange": "14:51 10/21/2011", "uuid": "1a6d4480-f4c8-11e0-be50-0800200c9a66" } ] 

Detalles

Tengo una serie de objetos que necesito para el servidor como JSON. Me parece que RestKit es la manera más fácil de hacer esto: estoy tratando de evitar convertir objetos en un conjunto de objetos NSDictionary , y luego usar un codificador JSON para obtener JSON que puedo POST al servidor.

Entonces, habiendo creado la matriz, y habiendo configurado la asignación para la clase de objetos almacenados en la matriz, naturalmente bash POST al servidor.

 RKObjectManager* mgr = [RKObjectManager objectManagerWithBaseURL:@"http://localhost/someweb/api/"]; mgr.serializationMIMEType = RKMIMETypeFormURLEncoded; mgr.client.username = @"username"; mgr.client.password = @"password"; RKObjectMapping* mapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]]; [mapping mapKeyPath: @"time" toAttribute:@"time" ]; [mapping mapKeyPath: @"someValue" toAttribute:@"someValue" ]; [mapping mapKeyPath: @"lastChange" toAttribute:@"lastChange" ]; [mapping mapKeyPath: @"uuid" toAttribute:@"uuid" ]; RKObjectMapping* mappingForSerialization = [mapping inverseMapping]; [mgr.mappingProvider setSerializationMapping:mappingForSerialization forClass:[NSManagedObject class]]; [mgr.router routeClass:[NSManagedObject class] toResourcePath:@"/sync" forMethod:RKRequestMethodPOST]; [mgr postObject:array delegate:nil/*self*/]; 

Sin embargo, esto es lo que obtengo:

 2011-10-11 14: 57: 51.769 AppConnect [1974: 6e0b] *** Aplicación de finalización debido a excepción no detectada '(null)', razón: 'No se puede encontrar una ruta enrutable para el objeto de tipo' __NSArrayI 'para el método HTTP 'ENVIAR''

Aparentemente, RestKit no sabe cómo manejar NSArray s.

¿Cómo se publica una matriz de objetos utilizando RestKit?


He intentado con algo diferente: reemplacé la última línea con un envío manual a través de RKObjectLoader .

 //[mgr postObject:[NSMutableDictionary dictionaryWithObject:array forKey:@"data"] delegate:nil/*self*/]; NSString* syncPath = @"/sync"; RKObjectLoader * objectLoader = [mgr objectLoaderWithResourcePath:syncPath delegate:self]; objectLoader.serializationMIMEType = RKMIMETypeJSON; objectLoader.method = RKRequestMethodPOST; //objectLoader.objectClass = [NSManagedObject class]; //objectLoader.managedObjectStore = mgr.objectStore; objectLoader.params = [NSDictionary dictionaryWithObject:array forKey:@"MyData"]; [objectLoader send]; 

Desafortunadamente, esto no aplica la asignación de ningún tipo, y en su lugar transmite una matriz de descripciones de objetos. El establecimiento de la serializationMIMEType tampoco afecta la estructura de los contenidos transmitidos, y los params siempre se transmiten como application/x-www-form-urlencoded .

También traté de asignar el mapeo de serialización y pasar el objeto como targetObject y sourceObject (esto parece ser lo que hace RestKit internamente -[RKObjectManager postObject:delegate:] ).

 RKObjectLoader * objectLoader = [mgr objectLoaderWithResourcePath:syncPath delegate:self]; objectLoader.method = RKRequestMethodPOST; //objectLoader.objectClass = [NSManagedObject class]; //objectLoader.managedObjectStore = mgr.objectStore; objectLoader.params = [NSMutableDictionary dictionaryWithObject:array forKey:@"MyData"]; objectLoader.serializationMapping = mapping; objectLoader.serializationMIMEType = RKMIMETypeJSON; objectLoader.sourceObject = objectLoader.params; objectLoader.targetObject = objectLoader.params; [objectLoader send]; 

Lamentablemente, no se realiza el mapeo de esta manera:

 2011-10-12 12:36:48.143 MyProject[5119:207] D restkit.network:RKObjectLoader.m:290 POST or PUT request for source object { MyData = ( " (entity: SomeRecord; id: 0x5934da0  ; data: )", " (entity: SomeRecord; id: 0x5934db0  ; data: )" ); }, serializing to MIME Type application/json for transport... 2011-10-12 12:36:48.143 MyProject[5119:207] D restkit.object_mapping:RKObjectMappingOperation.m:428 Starting mapping operation... 2011-10-12 12:36:48.145 MyProject[5119:207] T restkit.object_mapping:RKObjectMappingOperation.m:291 Did not find mappable attribute value keyPath 'time' 2011-10-12 12:36:48.145 MyProject[5119:207] T restkit.object_mapping:RKObjectMappingOperation.m:291 Did not find mappable attribute value keyPath 'someValue' 2011-10-12 12:36:48.145 MyProject[5119:207] T restkit.object_mapping:RKObjectMappingOperation.m:291 Did not find mappable attribute value keyPath 'lastChange' 2011-10-12 12:36:48.145 MyProject[5119:207] T restkit.object_mapping:RKObjectMappingOperation.m:291 Did not find mappable attribute value keyPath 'uuid' 2011-10-12 12:36:48.145 MyProject[5119:207] D restkit.object_mapping:RKObjectMappingOperation.m:448 Mapping operation did not find any mappable content 2011-10-12 12:36:48.146 MyProject[5119:207] T restkit.network:RKRequest.m:211 Prepared POST URLRequest ''. HTTP Headers: { Accept = "application/json"; "Content-Length" = 0; }. HTTP Body: . 

El restkit no financia la ruta enrutable para NSArray, porque definió su enrutamiento para la clase NSManagedObject . Probablemente desee crear una clase personalizada, digamos MySyncEntity que contenga los ivars que define en su mapeo. Entonces, creas tu mapeo de esta manera:

 RKObjectMapping* mapping = [RKObjectMapping mappingForClass:[MySyncEntity class]]; .... [myManager setSerializationMIMEType:RKMIMETypeJSON]; [[myManager router] routeClass:[MySyncEntity class] toResourcePath:@"/sync"]; 

entonces debería poder publicar su objeto en el backend API como objeto JSON.

Más aclaraciones:

En este caso, queremos publicar una matriz de instancias de NSManagedObject en una API basada en JSON. Para hacer eso, necesitamos crear una entidad de sincronización que contenga los objetos en una matriz:

 @interface MySyncEntity : NSObject {} @property (nonatomic, retain) NSArray* mySyncArray; ... @end 

mySyncArray contendrá la carga útil que nos gustaría enviar al rest del servidor. A continuación, creamos la asignación adecuada para NSManagedObject que se enviará en mySyncArray y la entidad MySyncEntity .

 RKObjectManager *manager = [RKObjectManager objectManagerWithBaseURL:kBaseUrl]; ... RKObjectMapping *mngObjMapping = [RKObjectMapping mappingForClass:[NSManagedObject class]]; [mngObjMapping mapKeyPath: @"time" toAttribute:@"time"]; [mngObjMapping mapKeyPath: @"recordLevel" toAttribute:@"recordLevel"]; .... //map as many properties as you wish [[manager mappingProvider] setSerializationMapping:[mngObjMapping inverseMapping] forClass:[NSManagedObject class]]; //now, we create mapping for the MySyncEntity RKObjectMapping *syncEntityMapping = [RKObjectMapping mappingForClass:[MySyncEntity class]]; [syncEntityMapping mapKeyPath:@"mySyncArray" toRelationship:@"mySyncArray" withMapping:mngObjMapping]; [[manager mappingProvider] setSerializationMapping:[syncEntityMapping inverseMapping] forClass:[MySyncEntity class]]; 

Ahora, con las asignaciones definidas, podemos publicar el objeto en el servidor

 [manager postObject:mySyncInstance delegate:nil]; 

El contenido de la matriz mySyncInstance se correlacionará de acuerdo con mngObjMapping y se enviará al punto final de descanso definido.

Como aclaración adicional, me gustaría señalar que en la respuesta de mja, la clave es

 [syncEntityMapping mapKeyPath:@"mySyncArray" toRelationship:@"mySyncArray" withMapping:mngObjMapping]; 

Esto dice “el mySyncArray mySyncArray es una matriz que contiene objetos que se deben mapear de acuerdo con mngObjMapping “.