11

你好,我是一个 NSObject 类型的类:

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

我想将“详细信息”对象传递给字典。

我做到了,

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

我将此字典传递给另一个对 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

4

9 回答 9

18

这可能是实现它的最简单方法。#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];
}
于 2013-09-29T17:45:02.793 回答
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

于 2013-09-29T17:14:27.233 回答
3

正如 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};
}

...

然后更改jsonObjectforProductDetails以使用它,例如:

@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];

NSKeyedArchiver如果您只是想将这些对象保存在文件中,我建议您使用NSKeyedUnarchiver. 但是,如果您需要为自己的私有类生成 JSON 对象,则可以执行上述操作。

于 2013-09-29T18:39:12.433 回答
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

在 .m 文件中

#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

如果有任何崩溃,您检查属性(NSMutableArray、NSString 等)在else if的条件内for

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

-(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);
    }
}
于 2015-03-17T09:40:47.160 回答
2

尝试这个:

#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];
}
于 2018-06-27T08:43:39.317 回答
1

做到这一点的完美方法是使用一个库进行序列化/反序列化,许多库都可用,但我喜欢 JagPropertyConverter https://github.com/jagill/JAGPropertyConverter

它可以将您的自定义对象转换为 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];
于 2014-06-19T05:58:11.983 回答
0

您还可以使用NSObject+APObjectMappingGitHub 上提供的类别: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];
于 2015-02-22T13:00:10.063 回答
0

尝试使用

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

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

于 2013-09-29T15:42:55.367 回答
0

您可以在objc/runtime.h类的帮助下在运行时将对象(例如 modelObject)转换为字典,但这有一定的限制,不推荐

考虑到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];
于 2017-12-09T08:12:21.013 回答