Group display of RestKit Arbitrary Keys objects

I have a JSON that looks like this:

{ "key1":[ { "desc":"key1decs.", "duration":50; },{ "desc":"", "duration":90; },{ "desc":"Kurz vor...", "duration":30; } ], "key2":[ { "desc":"key2decs.", "duration":50; },{ "desc":"blabla", "duration":90; } ] } 

I am trying to do a mapping. But I am stuck due to different unknown / arbitrary keys. I tried matching without KVC, but didn't seem to work. Gives me an error: Failed to convert the value to keyPath 'key1.desc'. There is no strategy to convert from '__NSArrayI' to 'NSString'. and so on for each attribute. I saw on the Internet that mapping without KVC does not support arrays, like internal structures. Plz help. What is the right approach?

EDIT: Entity:

 @interface Sendung : NSObject @property (nonatomic, strong) NSString *description; @property (nonatomic, strong) NSNumber *duration; @property (nonatomic, strong) NSNumber *sendungkey; @end; 

Controller:

  RKObjectMapping* mapping = [RKObjectMapping mappingForClass:[Sendung class]]; mapping.forceCollectionMapping = YES; [mapping mapKeyOfNestedDictionaryToAttribute:@"sendungkey"]; [mapping mapKeyPath:@"(sendungkey).desc" toAttribute:@"description"]; [mapping mapKeyPath:@"(sendungkey).duration" toAttribute:@"duration"]; [[RKObjectManager sharedManager].mappingProvider addObjectMapping:mapping ]; mapping = [[RKObjectManager sharedManager].mappingProvider objectMappingForClass:[Sendung class] ]; [[RKObjectManager sharedManager] loadObjectsAtResourcePath:url objectMapping:mapping delegate:self]; 

This is what I get when the NSlogin result is: ((zero), (zero), (zero), (zero), (zero))

+4
source share
1 answer

I believe that you are missing one β€œlevel” of your mapping. If you carefully consider your input, you have a dictionary (key1), the contents of which are not a single ' Sendung ', but an array of such objects. Thus, you cannot map the contents of key1 directly to Sendung ivars, and not create a new class, such as SendungResult .

 @interface SendungResult : NSObject @property (nonatomic, strong) NSString *keyName; @property (nonatomic, strong) NSArray *sendungs; @end 

and map the contents of the key1 array to SendungResult sendungs using the relationship mapping you are using right now.

EDIT: I am extending the answer as follows:

As I said before, you are trying to map a collection of objects to a single instance, so this will not work. Instead, you need to create a SendungResult that will contain an array of Sendung instances for a single key. Thus, in your example, you will get two SendungResult instances (one will contain three Sendung - those that are nested under "key1" , and the second - only two nested under "key2" ). You cannot map this type of structure to a class only, you must nest them in the same way as your JSON is nested. The Sendung class is basically unchanged.

Now for display. You need to define two mappings: one will map the contents of your root JSON to two SendungResult (one for each key), and the second map will map the inside to separate Sendung instances.

Let's start with the internal display.

 RKObjectMapping *sendungMapping = [RKObjectMapping mappingForClass:[Sendung class]]; [sendungMapping mapKeyPath:@"desc" toAttribute:@"desc"]; [sendungMapping mapKeyPath:@"duration" toAttribute:@"duration"]; [[[RKObjectManager sharedManager] mappingProvider] addObjectMapping:sendungMapping]; 

There is nothing interesting here, we just map the key paths to your properties. Now for the outside.

 RKObjectMapping *resultMapping = [RKObjectMapping mappingForClass:[SendungResult class]]; [resultMapping setForceCollectionMapping:YES]; [resultMapping mapKeyOfNestedDictionaryToAttribute:@"keyName"]; [resultMapping mapKeyPath:@"(keyName)" toRelationship:@"sendungs" withMapping:sendungMapping]; [[[RKObjectManager sharedManager] mappingProvider] addObjectMapping:resultMapping]; 

We tell RestKit to map the contents of the keyName keyPath property to the sendungs found in the SendungResult class with the mapping defined earlier.

Now we can get the data

 [[RKObjectManager sharedManager] loadObjectsAtResourcePath:@"test.js" objectMapping:resultMapping delegate:self]; 

RestKit will create two SendungResult instances, each array contains Sendung inner classes (3 and 2, respectively)

Note. . I highly recommend you read the RestKit Object Mapping documentation. In addition, JSONLint detected that your JSON is invalid, I had to remove the semicolons. So be sure to use valid json.

+5
source

Source: https://habr.com/ru/post/1381685/


All Articles