将NSObject转换为NSDictionary

时间:2013-09-29 15:39:02

标签: objective-c ios6 nsdictionary nsjsonserialization

你好我是NSObject类的一个类:

ProductDetails *details = [[ProductDetails alloc] init];
details.name = @"Soap1";
details.color = @"Red";
details.quantity = 4;

我想将“details”对象传递给字典。

我做了,

NSDictionary *dict = [NSDictionary dictionaryWithObject:details forKey:@"details"];

我将此dict传递给另一个执行JSONSerialization检查的方法:

if(![NSJSONSerialization isValidJSONObject:dict])

我在这张支票上遇到了崩溃。我在这里做错了吗?我知道我得到的细节是一个JSON对象,我将它分配给我的ProductDetails类中的属性。

请帮帮我。我是Objective-C的菜鸟。

我现在尝试过:

NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:(NSData*)details options:kNilOptions error:&error];

我需要的是将细节转换为NSData的简单方法。

我注意到我的对象里面有一个数组可能就是为什么我尝试的所有方法都抛出异常。然而,由于这个问题变得越来越大,我已经开始了另一个问题线程,在那里我显示了我在对象中的数据 - https://stackoverflow.com/questions/19081104/convert-nsobject-to-nsdictionary

9 个答案:

答案 0 :(得分:15)

这可能是实现它的最简单方法。在您的类文件中导入#import <objc/runtime.h>

#import <objc/runtime.h>

ProductDetails *details = [[ProductDetails alloc] init];
details.name = @"Soap1";
details.color = @"Red";
details.quantity = 4;
NSDictionary *dict = [self dictionaryWithPropertiesOfObject: details];
NSLog(@"%@", dict);

//Add this utility method in your class.
- (NSDictionary *) dictionaryWithPropertiesOfObject:(id)obj
{
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];

    unsigned count;
    objc_property_t *properties = class_copyPropertyList([obj class], &count);

    for (int i = 0; i < count; i++) {
        NSString *key = [NSString stringWithUTF8String:property_getName(properties[i])];
        [dict setObject:[obj valueForKey:key] forKey:key];
    }

    free(properties);

    return [NSDictionary dictionaryWithDictionary:dict];
}

答案 1 :(得分:14)

NSDictionary *details = {@"name":product.name,@"color":product.color,@"quantity":@(product.quantity)};

NSError *error; 
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:details 
                                                   options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string
                                                     error:&error];

if (! jsonData) {
    NSLog(@"Got an error: %@", error);
} else {
    NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}

第二部分来源:Generate JSON string from NSDictionary in iOS

答案 2 :(得分:3)

在.h文件中

#import <Foundation/Foundation.h>

@interface ContactDetail : NSObject
@property (nonatomic) NSString *firstName;
@property (nonatomic) NSString *lastName;
@property (nonatomic) NSString *fullName;
@property (nonatomic) NSMutableArray *mobileNumbers;
@property (nonatomic) NSMutableArray *Emails;
@property (assign) bool Isopen;
@property (assign) bool IsChecked;
-(NSDictionary *)dictionary;
@end
<。>文件中的

#import "ContactDetail.h"
#import <objc/runtime.h>

@implementation ContactDetail

@synthesize firstName;
@synthesize lastName;
@synthesize fullName;
@synthesize mobileNumbers;
@synthesize Emails;

@synthesize IsChecked,Isopen;

//-(NSDictionary *)dictionary {
//    return [NSDictionary dictionaryWithObjectsAndKeys:self.fullName,@"fullname",self.mobileNumbers,@"mobileNumbers",self.Emails,@"emails", nil];
//}

- (NSDictionary *)dictionary {
    unsigned int count = 0;
    NSMutableDictionary *dictionary = [NSMutableDictionary new];
    objc_property_t *properties = class_copyPropertyList([self class], &count);

    for (int i = 0; i < count; i++) {

        NSString *key = [NSString stringWithUTF8String:property_getName(properties[i])];
        id value = [self valueForKey:key];

        if (value == nil) {
            // nothing todo
        }
        else if ([value isKindOfClass:[NSNumber class]]
                 || [value isKindOfClass:[NSString class]]
                 || [value isKindOfClass:[NSDictionary class]] || [value isKindOfClass:[NSMutableArray class]]) {
            // TODO: extend to other types
            [dictionary setObject:value forKey:key];
        }
        else if ([value isKindOfClass:[NSObject class]]) {
            [dictionary setObject:[value dictionary] forKey:key];
        }
        else {
            NSLog(@"Invalid type for %@ (%@)", NSStringFromClass([self class]), key);
        }
    }
    free(properties);
    return dictionary;
}
@end

如果发生任何崩溃,你可以在 中的 else if else 条件中检查属性(NSMutableArray,NSString等)。

在您的控制器中,任何功能......

-(void)addItemViewController:(ConatctViewController *)controller didFinishEnteringItem:(NSMutableArray *)SelectedContact
{
    NSLog(@"%@",SelectedContact);

    NSMutableArray *myData = [[NSMutableArray alloc] init];
    for (ContactDetail *cont in SelectedContact) {
        [myData addObject:[cont dictionary]];
    }

    NSError *error = nil;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:myData options:NSJSONWritingPrettyPrinted error:&error];
    if ([jsonData length] > 0 &&
        error == nil){
//        NSLog(@"Successfully serialized the dictionary into data = %@", jsonData);
        NSString *jsonString = [[NSString alloc] initWithData:jsonData
                                                     encoding:NSUTF8StringEncoding];
        NSLog(@"JSON String = %@", jsonString);
    }
    else if ([jsonData length] == 0 &&
             error == nil){
        NSLog(@"No data was returned after serialization.");
    }
    else if (error != nil){
        NSLog(@"An error happened = %@", error);
    }
}

答案 3 :(得分:2)

正如mmackh所说,您希望为ProductDetails对象定义一个自定义方法,该方法将返回一个简单的NSDictionary值,例如:

@implementation ProductDetails

- (id)jsonObject
{
    return @{@"name"     : self.name,
             @"color"    : self.color,
             @"quantity" : @(self.quantity)};
}

...

假设我们向manufacturer添加了ProductDetails属性,该ManufacturerDetails引用了jsonObject类。我们也只为该课程编写@implementation ManufacturerDetails - (id)jsonObject { return @{@"name" : self.name, @"address1" : self.address1, @"address2" : self.address2, @"city" : self.city, ... @"phone" : self.phone}; } ...

jsonObject

然后更改ProductDetails的{​​{1}}以使用它,例如:

@implementation ProductDetails

- (id)jsonObject
{
    return @{@"name"         : self.name,
             @"color"        : self.color,
             @"quantity"     : @(self.quantity),
             @"manufacturer" : [self.manufacturer jsonObject]};
}

...

如果您有可能嵌套的集合对象(数组和/或字典)以及要编码的自定义对象,那么您也可以为每个对象编写jsonObject方法:

@interface NSDictionary (JsonObject)

- (id)jsonObject;

@end

@implementation NSDictionary (JsonObject)

- (id)jsonObject
{
    NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];

    [self enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
        if ([obj respondsToSelector:@selector(jsonObject)])
            [dictionary setObject:[obj jsonObject] forKey:key];
        else
            [dictionary setObject:obj forKey:key];
    }];

    return [NSDictionary dictionaryWithDictionary:dictionary];
}

@end

@interface NSArray (JsonObject)

- (id)jsonObject;

@end

@implementation NSArray (JsonObject)

- (id)jsonObject
{
    NSMutableArray *array = [NSMutableArray array];

    [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        if ([obj respondsToSelector:@selector(jsonObject)])
            [array addObject:[obj jsonObject]];
        else
            [array addObject:obj];
    }];

    return [NSArray arrayWithArray:array];
}

@end

如果您执行类似的操作,现在可以将自定义对象对象的数组或字典转换为可用于生成JSON的内容:

NSArray *products = @[[[Product alloc] initWithName:@"Prius"  color:@"Green" quantity:3],
                      [[Product alloc] initWithName:@"Accord" color:@"Black" quantity:1],
                      [[Product alloc] initWithName:@"Civic"  color:@"Blue"  quantity:2]];

id productsJsonObject = [products jsonObject];

NSError *error = nil;
NSData *data = [NSJSONSerialization dataWithJSONObject:productsJsonObject options:0 error:&error];

如果您只是想将这些对象保存在文件中,我建议NSKeyedArchiverNSKeyedUnarchiver。但是如果你需要为你自己的私有类生成JSON对象,你可以做类似上面的事情。

答案 4 :(得分:0)

尝试使用

NSDictionary *dict = [details valuesForAttributes:@[@"name", @"color"]];

并比较字典包含的内容。然后尝试将其转换为JSON。并查看JSON规范 - 哪些数据类型可以进入JSON编码文件?

答案 5 :(得分:0)

执行此操作的最佳方法是使用库进行序列化/反序列化 有很多图书馆,但我喜欢的是 JagPropertyConverter https://github.com/jagill/JAGPropertyConverter

它可以将您的Custom对象转换为NSDictionary,反之亦然 甚至它支持转换字典或数组或对象中的任何自定义对象(即组合)

JAGPropertyConverter *converter = [[JAGPropertyConverter alloc]init];
converter.classesToConvert = [NSSet setWithObjects:[ProductDetails class], nil];


//For Object to Dictionary 
NSDictionary *dictDetail = [converter convertToDictionary:detail];
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:dictDetail options:NSJSONWritingPrettyPrinted error:&error];

答案 6 :(得分:0)

您还可以使用GitHub上提供的NSObject+APObjectMapping类别:https://github.com/aperechnev/APObjectMapping

这很容易退出。只需在您的班级中描述映射规则:

#import <Foundation/Foundation.h>
#import "NSObject+APObjectMapping.h"

@interface MyCustomClass : NSObject
@property (nonatomic, strong) NSNumber * someNumber;
@property (nonatomic, strong) NSString * someString;
@end

@implementation MyCustomClass
+ (NSMutableDictionary *)objectMapping {
  NSMutableDictionary * mapping = [super objectMapping];
  if (mapping) {
    NSDictionary * objectMapping = @{ @"someNumber": @"some_number",
                                      @"someString": @"some_string" };
  }
  return mapping
}
@end

然后您可以轻松地将对象映射到字典:

MyCustomClass * myObj = [[MyCustomClass alloc] init];
myObj.someNumber = @1;
myObj.someString = @"some string";
NSDictionary * myDict = [myObj mapToDictionary];

您也可以从字典中解析对象:

NSDictionary * myDict = @{ @"some_number": @123,
                           @"some_string": @"some string" };
MyCustomClass * myObj = [[MyCustomClass alloc] initWithDictionary:myDict];

答案 7 :(得分:0)

您可以在 objc / runtime.h 类的帮助下在运行时将对象(比如modelObject)转换为字典,但这有一定的局限性并且不推荐。< / p>

考虑 MVC ,映射逻辑应该在Model类中实现。

@interface ModelObject : NSObject
@property (nonatomic) NSString *p1;
@property (nonatomic) NSString *p2;
-(NSDictionary *)dictionary;
@end


#import "ModelObject.h"

@implementation ModelObject
-(NSDictionary *)dictionary
{
    NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];

    [dict setValue:self.p1 forKey:@"p1"];// you can give different key name here if you want 
    [dict setValue:self.p2 forKey:@"p2" ];

    return dict;
}
@end

用途:

NSDictionary *modelObjDict = [modelObj dictionary];

答案 8 :(得分:0)

尝试一下:

#import <objc/runtime.h>

+ (NSDictionary *)dictionaryWithPropertiesOfObject:(id)obj {
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];

    unsigned count;
    objc_property_t *properties = class_copyPropertyList([obj class], &count);

    for (int i = 0; i < count; i++) {
        NSString *key = [NSString stringWithUTF8String:property_getName(properties[i])];
        [dict setObject:[obj valueForKey:key] ? [obj valueForKey:key] : @"" forKey:key];
    }

    free(properties);

    return [NSDictionary dictionaryWithDictionary:dict];
}