web-dev-qa-db-ja.com

NSObjectベースのクラスのiOSJSONシリアル化

自分のカスタムクラスをJSONでシリアル化したいのですが。私はObjective-C/iOS5で働いています。次のことをしたいのですが。

Person* person = [self getPerson ]; // Any custom object, NOT based on NSDictionary
NSString* jsonRepresentation = [JsonWriter stringWithObject:person ];
Person* clone = [JsonReader objectFromJson: jsonRepresentation withClass:[Person Class]];

NSJSONSerialization(および他のいくつかのライブラリ)では、「person」クラスがNSDictionaryなどに基づいている必要があるようです。定義したいカスタムオブジェクトを(理由の範囲内で)シリアル化するものが必要です。

Person.hが次のようになっていると想像してみましょう。

#import <Foundation/Foundation.h>
@interface Person : NSObject 
@property NSString* firstname;
@property NSString* surname;
@end

インスタンス用に生成されたJSONを次のようにしたいと思います。

{"firstname":"Jenson","surname":"Button"}

私のアプリはARCを使用しています。オブジェクトを使用してシリアル化と逆シリアル化の両方を行うものが必要です。

どうもありがとう。

18
Journeyman

JSONに入力できるデータは単純なオブジェクト(NSString、NSArray、NSNumberなど)だけであり、カスタムクラスやスカラー型ではないため、これは注意が必要です。どうして?これらすべてのデータ型をそれらのタイプのオブジェクトにラップするためのあらゆる種類の条件ステートメントを作成しない場合、解決策は次のようになります。

//at the top…
#import <objC/runtime.h>

    NSMutableDictionary *muteDictionary = [NSMutableDictionary dictionary];

    id YourClass = objc_getClass("YOURCLASSNAME");
    unsigned int outCount, i;
    objc_property_t *properties = class_copyPropertyList(YourClass, &outCount);
    for (i = 0; i < outCount; i++) {
        objc_property_t property = properties[i];
        NSString *propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
        SEL propertySelector = NSSelectorFromString(propertyName);
        if ([classInstance respondsToSelector:propertySelector]) {
            [muteDictionary setValue:[classInstance performSelector:propertySelector] forKey:propertyName];
        }
    }
    NSError *jsonError = nil;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:muteDictionary options:0 error:&jsonError];

私が前に述べたことのために、これはトリッキーです。スカラー型またはカスタムオブジェクトがある場合は、すべてが失敗します。このようなことを実行することが本当に重要な場合は、時間をかけて、値をNSDictionaryセーフオブジェクトにラップするために必要な条件ステートメントを支援するプロパティタイプを確認できるRicardのリンクを確認することをお勧めします。

23

これで、 JSONModel を使用してこの問題を簡単に解決できます。 JSONModelは、クラスに基づいてオブジェクトを一般的にシリアル化/逆シリアル化するライブラリです。 intshortfloatなどのプロパティに基づいた非nsobjectを使用することもできます。ネストされた複雑なJSONにも対応できます。

例を逆シリアル化します。あなたの例を参照すると、ヘッダーファイルで:

#import "JSONModel.h"

@interface Person : JSONModel 
@property (nonatomic, strong) NSString* firstname;
@property (nonatomic, strong) NSString* surname;
@end

実装ファイル内:

#import "JSONModelLib.h"
#import "yourPersonClass.h"

NSString *responseJSON = /*from somewhere*/;
Person *person = [[Person alloc] initWithString:responseJSON error:&err];
if (!err)
{
   NSLog(@"%@  %@", person.firstname, person.surname):
}

シリアル化の例。実装ファイル:

#import "JSONModelLib.h"
#import "yourPersonClass.h"

Person *person = [[Person alloc] init];
person.firstname = @"Jenson";
person.surname = @"Uee";

NSLog(@"%@", [person toJSONString]);
16
X Sham

多分これは役立つかもしれません JLObjectStrip

jacobが言ったことと同じですが、クラスのプロパティに対しても反復します。これにより、辞書/配列が得られ、sbjson/jsonkitまたはjson文字列を作成するために必要なものを使用するだけです。

1
Joshua

オブジェクトに対して行うことは、nsdictionaryを返す「toDict」というメソッドがあることです。この方法では、たとえば、必要な/必要なすべての属性を辞書に設定します

[user setObject:self.first_name forKey:@"first_name"];
[user setObject:self.last_name forKey:@"last_name"];
[user setObject:self.email forKey:@"email"];
0
Travis Delly

これを試してください BWJSONMatcher

とてもシンプルで便利です。

...
NSString *jsonString = @"{your-json-string}";
YourValueObject *dataModel = [YourValueObject fromJSONString:jsonString];

NSDictionary *jsonObject = @{your-json-object};
YourValueObject *dataModel = [YourValueObject fromJSONObject:jsonObject];
...
YourValueObject *dataModel = instance-of-your-value-object;
NSString *jsonString = [dataModel toJSONString];
NSDictionary *jsonObject = [dataModel toJSONObject];
...
0
Burrows Wang