objective-c 将 NSObject 转换为 NSDictionary
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19079862/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Converting NSObject to NSDictionary
提问by tech_human
Hello I a class of type NSObject:
你好,我是一个 NSObject 类型的类:
ProductDetails *details = [[ProductDetails alloc] init];
details.name = @"Soap1";
details.color = @"Red";
details.quantity = 4;
I want to pass the "details" object to a dictionary.
我想将“详细信息”对象传递给字典。
I did,
我做了,
NSDictionary *dict = [NSDictionary dictionaryWithObject:details forKey:@"details"];
I am passing this dict to another method which performs a check on JSONSerialization:
我将此字典传递给另一个对 JSONSerialization 执行检查的方法:
if(![NSJSONSerialization isValidJSONObject:dict])
And I am getting a crash on this check. Am I doing anything wrong here? I know that the details I am getting is a JSON object and I am assigning it to the properties in my ProductDetails class.
我在这张支票上崩溃了。我在这里做错了什么吗?我知道我得到的细节是一个 JSON 对象,我将它分配给我的 ProductDetails 类中的属性。
Please help me. I am a noob in Objective-C.
请帮我。我是 Objective-C 的菜鸟。
I now tried:
我现在尝试:
NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:(NSData*)details options:kNilOptions error:&error];
All I need here is an easy way to convert details to NSData.
我所需要的只是一种将详细信息转换为 NSData 的简单方法。
I noticed that I have an array inside my object may be thats why all the ways I tried is throwing an exception. However since this question is becoming to big, I have started an another question thread for it where I have displayed the data I am getting inside the object - https://stackoverflow.com/questions/19081104/convert-nsobject-to-nsdictionary
我注意到我的对象中有一个数组,这可能就是我尝试的所有方法都抛出异常的原因。然而,由于这个问题变得越来越大,我已经开始了另一个问题线程,我已经显示了我在对象中获取的数据 - https://stackoverflow.com/questions/19081104/convert-nsobject-to-nsdictionary
回答by thatzprem
This may well be the easiest way to achieve it. Do import #import <objc/runtime.h>in your class file.
这很可能是实现它的最简单方法。#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];
}
回答by mmackh
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];
}
Second part's source: Generate JSON string from NSDictionary in iOS
回答by Mohamed Jaleel Nazir
In .h File
在 .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
in .m file
在 .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
if any crash ,You check the property (NSMutableArray,NSString,etc ) in else ifcondition inside of for.
如果任何崩溃,你在检查属性(NSMutableArray里,NSString的,等),否则,如果条件内进行。
In Your Controller, in any func...
在您的控制器中,在任何功能...
-(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);
}
}
回答by Rob
As mmackh said, you want to define a custom method for your ProductDetailsobject that will return a simple NSDictionaryof values, e.g.:
正如 mmackh 所说,您想为您的ProductDetails对象定义一个自定义方法,该方法将返回一个简单NSDictionary的值,例如:
@implementation ProductDetails
- (id)jsonObject
{
return @{@"name" : self.name,
@"color" : self.color,
@"quantity" : @(self.quantity)};
}
...
Let's assume that we added manufacturerproperty to our ProductDetails, which referenced a ManufacturerDetailsclass. We'd just write a jsonObjectfor that class, too:
假设我们将manufacturer属性添加到我们的ProductDetails,它引用了一个ManufacturerDetails类。我们也只是jsonObject为那个类写一个:
@implementation ManufacturerDetails
- (id)jsonObject
{
return @{@"name" : self.name,
@"address1" : self.address1,
@"address2" : self.address2,
@"city" : self.city,
...
@"phone" : self.phone};
}
...
And then change the jsonObjectfor ProductDetailsto employ that, e.g.:
然后更改jsonObjectforProductDetails以使用它,例如:
@implementation ProductDetails
- (id)jsonObject
{
return @{@"name" : self.name,
@"color" : self.color,
@"quantity" : @(self.quantity),
@"manufacturer" : [self.manufacturer jsonObject]};
}
...
If you have potentially nested collection objects (arrays and/or dictionaries) with custom objects that you want to encode, you could write a jsonObjectmethod for each of those, too:
如果您有潜在的嵌套集合对象(数组和/或字典)和要编码的自定义对象,您也可以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
If you do something like that, you can now convert arrays or dictionaries of your custom objects object into something that can be used for generating JSON:
如果您执行类似的操作,您现在可以将自定义对象对象的数组或字典转换为可用于生成 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];
If you're simply trying to save these objects in a file, I'd suggest NSKeyedArchiverand NSKeyedUnarchiver. But if you need to generate JSON objects for your own private classes, you can do something like the above might work.
如果您只是想将这些对象保存在一个文件中,我建议您使用NSKeyedArchiver和NSKeyedUnarchiver. 但是,如果您需要为自己的私有类生成 JSON 对象,则可以执行上述操作。
回答by M.Shuaib Imran
The perfect way to do this is by using a library for serialization/deserialization many libraries are available but one i like is JagPropertyConverter https://github.com/jagill/JAGPropertyConverter
做到这一点的完美方法是使用库进行序列化/反序列化,许多库可用,但我喜欢的是 JagPropertyConverter https://github.com/jagill/JAGPropertyConverter
it can convert your Custom object into NSDictionary and vice versa
even it support to convert dictionary or array or any custom object within your object (i.e Composition)
它可以将您的自定义对象转换为 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];
回答by Alexander Perechnev
You also can use the NSObject+APObjectMappingcategory which is available on GitHub: https://github.com/aperechnev/APObjectMapping
您也可以使用NSObject+APObjectMappingGitHub 上提供的类别:https: //github.com/aperechnev/APObjectMapping
It's a quit easy. Just describe the mapping rules in your class:
这是一个退出容易。只需描述您班级中的映射规则:
#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
And then you can easily map your object to dictionary:
然后您可以轻松地将您的对象映射到字典:
MyCustomClass * myObj = [[MyCustomClass alloc] init];
myObj.someNumber = @1;
myObj.someString = @"some string";
NSDictionary * myDict = [myObj mapToDictionary];
Also you can parse your object from dictionary:
你也可以从字典中解析你的对象:
NSDictionary * myDict = @{ @"some_number": @123,
@"some_string": @"some string" };
MyCustomClass * myObj = [[MyCustomClass alloc] initWithDictionary:myDict];
回答by PANKAJ VERMA
You can convert object (say modelObject) to dictionary at runtime with the help of objc/runtime.hclass but that has certain limitations and is not recommended.
您可以在objc/runtime.h类的帮助下在运行时将对象(例如 modelObject)转换为字典,但这有一定的限制,不推荐使用。
Considering MVC, mapping logic should be implemented in Model class.
考虑到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
Uses:
用途:
NSDictionary *modelObjDict = [modelObj dictionary];
回答by u5133716
Try this:
尝试这个:
#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];
}
回答by Wain
Try using
尝试使用
NSDictionary *dict = [details valuesForAttributes:@[@"name", @"color"]];
And compare what the dictionary contains. Then try to convert it to JSON. And look at the JSON spec - what data types can go into a JSON encoded file?
并比较字典包含的内容。然后尝试将其转换为 JSON。并查看 JSON 规范 - 哪些数据类型可以进入 JSON 编码文件?

