3

我一直在寻找是否可以获取 JSON 字典或数组并将其直接映射到其属性与 JSON 标签同名的自定义对象中,但我找不到任何相关信息。

我一直在手动解析 JSON 字典,如下所示:

id deserializedObj = nil;
id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData
                                                options:NSJSONReadingAllowFragments
                                                  error:&error];
if ([jsonObject isKindOfClass:[NSDictionary class]]) {
        NSDictionary *jsonDictionary = (NSDictionary *)jsonObject;

  if ([jsonDictionary objectForKey:idTag] != [NSNull null])
     [myObject setID:[[jsonDictionary objectForKey:@"id"] integerValue]];

  // Rest of properties
}

但是我发现必须手动解析每个字典条目并且没有办法将其直接序列化为自定义对象,这很奇怪,难道没有其他更快的方法吗?

注意:我需要我的应用与 iOS 5+ 兼容

提前致谢

4

3 回答 3

8

我会向您推荐一个名为Motis的图书馆。它是 NSObject 上的一个类别,通过 KeyValueCoding 进行对象映射。这个类别的好处是非常轻量级并且执行自动值验证以尝试适合您的属性的类类型(通过自省)。

最重要的是,您需要做的是在您的 NSObject 子类中使用“JSONKey”:“PropertyName”对定义映射(字典)。

此外,如果您有数组,则可以定义从数组名称到其内容的类类型的映射,从而为数组内容启用自动对象映射。

例如,如果我们尝试将以下 JSON 映射到我们的自定义对象:

{"video_id": 23,
 "video_title": "My holidays in Paris",
 "video_uploader":{"user_id":55,
                   "user_username": "johndoe"
                  },
 "video_people":[{"user_id":55,
                   "user_username": "johndoe"
                 },
                 {"user_id":45,
                   "user_username": "jimmy"
                 },
                 {"user_id":55,
                   "user_username": "martha"
                 }
                ]
 }

我们将在我们的 NSObject 子类中实现:

// --- Video Object --- //
@interface Video : NSObject
@property (nonatomic, assing) NSInteger videoId; 
@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) User *uploader;
@property (nonatomic, strong) NSArray *peopleInVideo; // <-- Array of users
@end

@implementation Video
+ (NSDictionary*)mts_mapping
{
    return @{@"video_id" : mts_key(videoId),
             @"video_title" : mts_key(title),
             @"video_uploader" : mtsk_key(uploader),
             @"video_people": mts_key(peopleInVideo),
            };
}

+ (NSDictionary*)mts_arrayClassMapping
{
    return @{mts_key(peopleInVideo): User.class};
}

@end

// --- User Object --- //
@interface User : NSObject
@property (nonatomic, assing) NSInteger userId; 
@property (nonatomic, strong) NSString *username;
@end

@implementation User
+ (NSDictionary*)mts_mapping
{
    return @{@"user_id" : mts_key(userId),
             @"user_username" : mts_key(username),
            };
}

@end

并执行解析和对象映射:

NSData *data = ... // <-- The JSON data
NSError *error = nil;
NSDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];

if (error)
    return; // if error, abort.

Video *video = [[Video alloc] init];
[video mts_setValuesForKeysInDictionary:jsonObject]; // <-- Motis Object Mapping 

NSLog(@"Video: %@", video.description);

就这么简单。在这里你可以阅读更多关于它的信息:http: //github.com/mobilejazz/Motis

有关更多信息,请查看我在MobileJazz 博客中写的关于使用 KeyValueCoding 和分布式对象映射的好处的博客文章。

希望能有所帮助。

于 2014-03-18T09:28:10.373 回答
5

您可以尝试使用受RestKit启发的 JTObjectMapping。

另一种方法是首先从字典中删除 null 和 nil 值。使用为您的子类中的 keypath 的键创建映射setValue:forKeyPath:

于 2013-07-29T17:05:33.243 回答
4

您可以使用它们的属性创建自己的 NSObject 子类,并在循环中使用键值编码填充它们,您可以在其中探索从 JSON 反序列化返回的所有 NSDictionary 键。当然,每个字典键都应该匹配一个对象属性。 键值编码

于 2013-07-29T17:00:16.923 回答