2013/12/10

モデルクラスとNSDictionaryとの相互変換を楽に行えるようにするライブラリMantleを試す

MantleはGitHubの人 (かつ、ReactiveCocoaの人) が開発したモデルフレームワークです (ライセンス: MIT)。

簡単に言えばNSCodingの代わりになるようなもので、NSCodingに比べてコード量が少なくなるように設計されています。

インストール

CocoaPodsを利用するだけです。

まずは単純な例として、プロパティのみを持っている次のようなクラスがあるとします。

@interface FOOSampleModel : NSObject
@property (strong, nonatomic) NSString* userId;
@property (strong, nonatomic) NSString* userName;
@property (strong, nonatomic) NSString* secretKey;
@end

Mantleを利用するには、対象とするモデルのクラスをMTLModel のサブクラスにするだけです。

よって、インタフェースは次のようになります。

@interface FOOSampleModel : MTLModel<MTLJSONSerializing>
@property (strong, nonatomic) NSString* userId;
@property (strong, nonatomic) NSString* userName;
@property (strong, nonatomic) NSString* secretKey;
@end

実装側ではMTLJSONSerializingの必須メソッドである+JSONKeyPathsByPropertyKeyを実装します。

これはとりあえず空のディクショナリを返しておけばよいです。

@implementation FOOSampleModel
+ (NSDictionary*)JSONKeyPathsByPropertyKey {
    return @{};
}
@end

モデルからNSDictionaryに変換 (シリアライズ)

上記のような手順のみで、モデルとNSDictionaryが相互変換できるようになります。

FOOSampleModel* model = [[FOOSampleModel alloc] init];
model.userId = @"12345";
model.userName = @"Foo Bar";
model.secretKey = @"SECRET!!";

モデルからNSDictionaryに変換は次のように行います。

NSDictionary* dic = [MTLJSONAdapter JSONDictionaryFromModel:model];
NSLog(@"%@", dic);

デフォルトで全プロパティがシリアライズされますので、このときの結果は次のようになります。

2013-12-09 23:05:03.041 XcodeSample[53413:70b] {
    secretKey = "SECRET!!";
    userId = 12345;
    userName = "Foo Bar";
}

NSDictionaryからモデルに変換 (デシリアライズ)

NSDictionaryからモデルに変換も次のように非常に簡単です。

NSError* error = nil;
FOOSampleModel* model = [MTLJSONAdapter modelOfClass:FOOSampleModel.class fromJSONDictionary:dic error:&error];

なお、プロパティにないものはデシリアライズ時に無視されます。

シリアライズする内容を修正する

先ほど戻り値を空のディクショナリにしていた+JSONKeyPathsByPropertyKeyの戻り値を修正することでシリアライズの内容をカスタマイズできます。

  • ディクショナリに@"プロパティ名": @"JSON名"で入れる。
  • デシリアライズしたくないものは@"プロパティ名": NSNull.null

例えば次のように変更した場合には…

+ (NSDictionary *)JSONKeyPathsByPropertyKey {
    return @{
        @"userId": @"user-id",
        @"userName": @"user-name",
        @"secretKey": NSNull.null
    };
}

出力結果は次のようになります。

2013-12-09 23:04:20.690 XcodeSample[53152:70b] {
    "user-id" = 12345;
    "user-name" = "Foo Bar";
}

(おまけ) NSDictionaryからファイルに保存する

次のどちらかを利用します。

{
    NSData* data = [NSJSONSerialization dataWithJSONObject:dic options:0 error:&error];
    [data writeToFile:path atomically:YES];
}
{
    NSOutputStream* output = [NSOutputStream outputStreamToFileAtPath:path append:NO];
    [output open];
    [NSJSONSerialization writeJSONObject:dic toStream:output options:0 error:&error];
    [output close];
}

(おまけ) JSONファイルからNSDictionaryに変換する

次のどちらかを利用します。

{
    NSData* data = [NSData dataWithContentsOfFile:path options:0 error:&error];
    NSDictionary* dic = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
}
{
    NSInputStream* input = [NSInputStream inputStreamWithFileAtPath:path];
    [input open];
    NSDictionary* dic = [NSJSONSerialization JSONObjectWithStream:input options:0 error:&error];
    [input close];
}

おわりに

Mantleの使いかたを簡単に紹介しました。

関連リンク

0 件のコメント:

コメントを投稿

注: コメントを投稿できるのは、このブログのメンバーだけです。