4

ここに次のような JSON があります。

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

マッピングをしようとしています。しかし、不明な/任意のキーが異なるため、私は立ち往生しています。KVC なしでマッピングを試みましたが、うまくいかないようです。エラーが表示されます: keyPath 'key1.desc' での値の変換に失敗しました。「__NSArrayI」から「NSString」に変換するための戦略はありません。など、すべての属性について。KVC を使用しないマッピングでは配列を内部構造としてサポートしていないことを Web で見ました。助けてください。ここで正しいアプローチは何ですか?

編集:エンティティ:

@interface Sendung : NSObject

 @property (nonatomic, strong) NSString *description;
 @property (nonatomic, strong) NSNumber *duration;
 @property (nonatomic, strong) NSNumber *sendungkey;
@end;

コントローラ:

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

これは、NSloginの結果として得られるものです: ( (null), (null), (null), (null), (null) )

4

1 に答える 1

5

マッピングの 1 つの「レベル」を見逃していると思います。入力を詳しく見てみると、辞書 (key1) があり、その内容は単一の ' Sendung' ではなく、そのようなオブジェクトの配列です。Sendungしたがって、新しいクラスを作成するのではなく、key1の内容を ivar に直接マップすることはできませんSendungResult

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

SendungResult sendungsそして、現在使用している関係マッピングを直接使用して、key1 の内容を配列にマッピングします。

編集:次のように答えを拡張しています:

前述したように、オブジェクトのコレクションを単一のインスタンスにマップしようとしているため、これは機能しません。代わりに、1 つのキーのインスタンスSendungResultの配列を保持するを作成する必要があります。Sendungしたがって、あなたの例では、2 つのSendungResultインスタンスになります (1 つは 3 つSendungの s を保持します - 下にネストされたものと、2 つ目は の下にネストされ"key1"た 2 つだけ"key2"です)。この種の構造を一度だけクラスにマップすることはできません。JSON がネストされているのと同じ方法でネストする必要があります。クラスはSendung基本的に変わりません。

いよいよマッピングです。2 つのマッピングを定義する必要があります。1 つはルート JSON の内容を 2 つSendungResult(キーごとに 1 つ) にマッピングし、2 つ目のマッピングは内部部分を個々のSendungインスタンスにマッピングします。

内部マッピングから始めます。

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

ここでは特に興味深いことはありません。キーパスをプロパティにマッピングするだけです。今度は外側の部分です。

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

前に定義したマッピングを使用して、RestKit に keyName keyPath の内容をクラスでsendungs見つかったプロパティにマップするように指示しますSendungResult

これでデータを取得できます

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

RestKit は 2 つのSendungResultインスタンスを作成し、各配列には内部Sendungクラス (それぞれ 3 と 2)が含まれます。

注: RestKit オブジェクト マッピングのドキュメントを読むことを強くお勧めします。また、JSONLint は JSON が無効であることを検出しました。セミコロンを削除する必要がありました。そのため、必ず有効な json を使用してください。

于 2011-11-17T15:32:44.997 に答える