RestKit: как разместить массив объектов?

Резюме вопроса:

Рассмотрим класс SyncObject это KVC-совместимые свойства, такие как: time, someValue, lastChange, uuid,

Рассмотрим NSArray содержащие исключительно случаи SyncObject,

Мне нужно отправить массив на сервер в виде массива JSON.

Как отправить этот массив на сервер, используя HTTP POST, используя RestKit?

Пример массива:

[
  {
    "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"
  }
]

подробности

У меня есть массив объектов, которые мне нужны на сервере, как JSON. Мне кажется, что RestKit - это самый простой способ сделать это: я пытаюсь избежать преобразования объектов в набор NSDictionary объекты, а затем с помощью некоторого кодера JSON, чтобы получить JSON, который я могу POST на сервер.

Итак, создав массив и настроив отображение для класса объектов, хранящихся в массиве, я, естественно, пытаюсь POST на сервер.

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*/];

Тем не менее, это то, что я получаю:

2011-10-11 14: 57: 51.769 AppConnect [1974: 6e0b] *** Завершение работы приложения из-за необработанного исключения '(null)', причина: 'Невозможно найти маршрутизируемый путь для объекта типа'__NSArrayI'для метода HTTP 'СООБЩЕНИЕ''

Судя по всему, RestKit не умеет обращаться NSArrays.

Как разместить массив объектов, используя RestKit?


Я пробовал что-то другое: я заменил последнюю строку с ручной отправки через 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];

К сожалению, это не относится к отображению любого вида, а вместо этого передает массив описаний объектов. настройка serializationMIMEType также не влияет на структуру передаваемого содержимого, и params всегда передаются как application/x-www-form-urlencoded,

Я также попытался назначить отображение сериализации и передать объект как targetObject а также sourceObject (похоже, что RestKit делает это внутри -[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];

К сожалению, отображение не происходит таким образом:

2011-10-12 12:36:48.143 MyProject[5119:207] D restkit.network:RKObjectLoader.m:290 POST or PUT request for source object {
    MyData =     (
        "<NSManagedObject: 0x5935430> (entity: SomeRecord; id: 0x5934da0 <x-coredata://64DF9977-DA50-4FCD-8C20-4132E58439BF/SomeRecord/p1> ; data: <fault>)",
        "<NSManagedObject: 0x5935730> (entity: SomeRecord; id: 0x5934db0 <x-coredata://64DF9977-DA50-4FCD-8C20-4132E58439BF/SomeRecord/p2> ; data: <fault>)"
    );
}, 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 '<NSMutableURLRequest http://someurl/api/sync?request=provide_key>'. HTTP Headers: {
    Accept = "application/json";
    "Content-Length" = 0;
}. HTTP Body: .

2 ответа

Решение

Restkit не финансирует маршрутизируемый путь для NSArray, потому что вы определили свою маршрутизацию для NSManagedObject учебный класс. Вы, вероятно, хотите создать собственный класс, скажем, MySyncEntity который содержит ивы, которые вы определили в своем отображении. Затем вы создаете свое отображение следующим образом:

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

тогда вы сможете отправить свой объект в бэкэнд API как объект JSON.

Дальнейшее уточнение:

В этом случае мы хотим опубликовать массив NSManagedObject экземпляры в API на основе JSON. Для этого нам нужно создать синхронизирующую сущность, которая содержит объекты в массиве:

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

mySyncArray будет содержать полезную нагрузку, которую мы хотели бы передать остальному бэкэнду. Затем мы создаем соответствующее отображение для обоих NSManagedObject это будет отправлено в mySyncArray и 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]];

Теперь с определенными отображениями мы можем отправить объект на сервер

[manager postObject:mySyncInstance delegate:nil];

Содержание mySyncInstance массив будет отображен в соответствии с mngObjMapping и отправлен в определенную конечную точку отдыха.

В качестве дальнейшего разъяснения, я хотел бы указать, что в ответе mja главное

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

Это говорит " mySyncArray keypath - это массив, который содержит объекты, которые должны отображаться в соответствии с mngObjMapping".

Другие вопросы по тегам