我正在与rest工具包0.20.3为一些项目,现在没有问题。现在,我面临的问题是JSON键导致"@“,这会导致Restkit在映射数据时崩溃。
JSON看起来如下所示:
{
"city": {
"@name": "Charles Redirection City",
"@nameUrl": "Charles Redirection City",
"lat": "52.5238",
"long": "13.4119",
"zipCode": "666"
},
"categories": {
"@count": "20037",
"category": [
{
"@count": "2326",
"@hasChildren": "true",
"id": "15777",
"name": "Sticky-Categorie"
}
]
},
"additional": {
"dataKey": [
{
"@key": "log-start",
"$": "home"
}
]
}
}在将应用程序映射为
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSCFDictionary 0x95b5360> valueForUndefinedKey:]: this class is not key value coding-compliant for the key hasChildren.'当它试图在字典上调用hasChildren时。我的地图如下所示:
[mapping addAttributeMappingsFromDictionary:@{
@"id" : @"categoryId",
@"name" : @"name",
@"@hasChildren" : @"doesHaveChildren",
@"@count" : @"numbersOfJobs",
@"trackingName" : @"trackingString"
}];我已经尝试了应用我自己的映射,但不幸的是,它没有起作用。在RestKit中是否不支持前导@?我已经用NSJSONSerialization解析了JSON,它工作得很好,但是我非常喜欢RestKit的映射特性,并且希望避免编写自己的映射:)
发布于 2014-06-18 16:30:16
@用于键值编码
集合运算符是作为参数传递给
valueForKeyPath:方法的专用密钥路径。运算符由一个字符串指定,前面有一个at符号(@)。
我不知道有什么方法可以让NSDictionary忽略它。您可以从JSON中删除@,无论是在服务器端,还是在收到JSON之后,但在将其交给RestKit的映射程序之前。
发布于 2014-06-18 16:39:31
其想法是,例如,用新键重新构建字典,它将不包含任何@字符。这就是在键中有NSDictionary字符的@中读取值的方法。
我只是将@键替换为顶层的_,用于新字典:
NSDictionary *_dictionary; // your original dictionary
NSMutableDictionary *_validatedDictionary = [NSMutableDictionary dictionary];
[_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString * key, id obj, BOOL *stop) {
NSString *_validKey = [key stringByReplacingOccurrencesOfString:@"@" withString:@"_"];
[_validatedDictionary setObject:obj forKey:_validKey];
}];注意:这只是一个只在我的代码中在顶层工作的概念想法,您可以使用它来创建一个递归算法来取代更深层次的算法。
发布于 2014-06-18 17:32:40
如果无法替换移除@的键,则还有另一种解决方案可供测试。
这可能有点激烈,但您可以尝试将NSDictionary子类替换为-(id)valueForKeyPath:(NSString *)keyPath方法的实现。
我说这很激烈,因为对类集群进行子类化(像NSDictionary这样的子类从来就不容易),您必须做很多测试才能确保RestKit不会抱怨这一点。
此外,如果RestKit以“自定义”的方式复制字典(例如,从零开始构造一个全新的NSDictionary,而不是在我们的自定义子类上使用副本),这是行不通的。
目标是有一个子类来实现这样的方法
-(id)valueForKeyPath:(NSString *)keyPath
{
if ([[keyPath substringToIndex:1] isEqualToString:@"@"])
{
return [_subDictionary objectForKey:keyPath]; // if the first character is @, return the result of objectForKey
} else {
return [_subDictionary valueForKeyPath:keyPath];
}
}您可以更改方法以返回objectForKey的值,而不是仅在某些情况下才返回valueForKeyPath的值(例如,如果键是"@hasChildren“)。
这将给你这个结果:
self.aDictionary = [[FLDictionary alloc] initWithObjects:@[@"pluto"] forKeys:@[@"@pippo"]];
NSLog(@"Value is %@", [self valueForKeyPath:@"aDictionary.@pippo"]);
NSLog result: 2014-06-18 19:24:34.605 Swift123[25663:454958] Value is pluto然而,现在出现了困难的部分。为了子类NSDictionary (类集群),您必须重写以下方法:
-(instancetype)initWithObjects:(const id [])objects forKeys:(const id<NSCopying> [])keys count:(NSUInteger)cnt;
-(NSUInteger)count;
-(id)objectForKey:(id)aKey;
-(NSEnumerator *)keyEnumerator;重写意味着您应该为新创建的字典实现自己的存储。为了避免这种情况,我创建了一个带有底层NSDictionary的实例变量。我将在文章的末尾发布完整的代码。
另外要注意的是:复制NSDictionaries是一种惯例。这将导致您的自定义类在第一个副本时被提交到一个标准的NSDictionary中。因此,您甚至必须对copyWithZone:方法进行子类化。
这里是一个完整的工作示例:
//
// FLDictionary.m
// Swift123
//
// Created by Lombardo on 18/06/14.
// Copyright (c) 2014 Lombardo. All rights reserved.
//进口"FLDictionary.h“
@interface FLDictionary ()
@property (copy, nonatomic) NSDictionary *subDictionary;
@end
@implementation FLDictionary
-(instancetype)initWithObjects:(const id [])objects forKeys:(const id<NSCopying> [])keys count:(NSUInteger)cnt
{
self = [self init];
if (self) {
_subDictionary = [[NSDictionary alloc] initWithObjects:objects forKeys:keys count:cnt];
}
return self;
}
-(NSUInteger)count
{
return [_subDictionary count];
}
-(id)objectForKey:(id)aKey
{
return [_subDictionary objectForKey:aKey];
}
-(NSEnumerator *)keyEnumerator
{
return [_subDictionary keyEnumerator];
}
-(id)valueForKeyPath:(NSString *)keyPath
{
if ([[keyPath substringToIndex:1] isEqualToString:@"@"])
{
return [_subDictionary objectForKey:keyPath];
} else {
return [_subDictionary valueForKeyPath:keyPath];
}
}
-(id)copyWithZone:(NSZone *)zone
{
id objects[ [_subDictionary count] ];
id keys[ [_subDictionary count] ];
int i = 0;
for (id item in [_subDictionary allValues])
{
objects[i++] = item;
}
i = 0;
for (id item in [_subDictionary allKeys])
{
keys[i++] = item;
}
FLDictionary *dict = [[[self class] allocWithZone:zone] initWithObjects:objects forKeys:keys count:[_subDictionary count]];
return dict;
}
@endhttps://stackoverflow.com/questions/24290577
复制相似问题