webentwicklung-frage-antwort-db.com.de

Konvertieren von NSObject in NSDictionary

Hallo ich eine Klasse vom Typ NSObject:

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

Ich möchte das "Details" -Objekt an ein Wörterbuch übergeben. 

Ich tat, 

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

Ich gebe dieses Diktat an eine andere Methode weiter, die eine Überprüfung der JSONSerialization durchführt:

if(![NSJSONSerialization isValidJSONObject:dict])

Und ich bekomme einen Absturz bei diesem Check. Mache ich hier etwas falsch? Ich weiß, dass die Details, die ich erhalte, ein JSON-Objekt sind, und ich weise es den Eigenschaften in meiner ProductDetails-Klasse zu.

Bitte hilf mir. Ich bin ein Noob in Objective-C.

Ich habe jetzt versucht:

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

Ich brauche hier nur eine einfache Möglichkeit, Details in NSData umzuwandeln. 

Mir ist aufgefallen, dass ich ein Array in meinem Objekt habe. Dies ist der Grund, warum ich versucht habe, eine Ausnahme auszulösen. Da diese Frage jedoch zu groß wird, habe ich einen weiteren Fragethread dafür gestartet, in dem ich die Daten angezeigt habe, die ich in dem Objekt erhalten habe - https://stackoverflow.com/questions/19081104/convert-nsobject-to -nsdictionary

9
tech_human
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];
}

Quelle des zweiten Teils: Generiere JSON-String aus NSDictionary in iOS

13
mmackh

Dies ist möglicherweise der einfachste Weg, um dies zu erreichen. Importieren Sie #import <objc/runtime.h> in Ihre Klassendatei.

#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];
}
15
thatzprem

In .h-Datei

#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-Datei

#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

bei einem Absturz prüfen Sie die Eigenschaft (NSMutableArray, NSString usw.) in, falls Bedingung innerhalb von für .

In Ihrem Controller, in jeder Funktion ...

-(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
Jaleel Nazir

Wie mmackh sagte, möchten Sie eine benutzerdefinierte Methode für Ihr ProductDetails-Objekt definieren, die eine einfache NSDictionary von Werten zurückgibt, z. B .:

@implementation ProductDetails

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

...

Nehmen wir an, dass wir unserer manufacturer die ProductDetails -Eigenschaft hinzugefügt haben, die auf eine ManufacturerDetails-Klasse verweist. Wir würden auch nur eine jsonObject für diese Klasse schreiben:

@implementation ManufacturerDetails

- (id)jsonObject
{
    return @{@"name"     : self.name,
             @"address1" : self.address1,
             @"address2" : self.address2,
             @"city"     : self.city,
             ...
             @"phone"    : self.phone};
}

...

Ändern Sie dann die Variable jsonObject für ProductDetails, um diese zu verwenden, z.

@implementation ProductDetails

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

...

Wenn Sie potenziell verschachtelte Sammlungsobjekte (Arrays und/oder Wörterbücher) mit benutzerdefinierten Objekten haben, die Sie kodieren möchten, können Sie auch eine jsonObject-Methode für jedes dieser Objekte schreiben:

@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

Wenn Sie so etwas tun, können Sie jetzt Arrays oder Wörterbücher Ihres benutzerdefinierten Objektobjekts in etwas konvertieren, das zum Generieren von JSON verwendet werden kann:

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

Wenn Sie lediglich versuchen, diese Objekte in einer Datei zu speichern, würde ich NSKeyedArchiver und NSKeyedUnarchiver vorschlagen. Wenn Sie jedoch JSON-Objekte für Ihre eigenen privaten Klassen generieren müssen, können Sie so etwas wie das oben genannte tun.

2
Rob

Sie können ein Objekt (z. B. modelObject) zur Laufzeit mit Hilfe von objc/runtime.h class in ein Wörterbuch konvertieren. Dies hat jedoch bestimmte Einschränkungen und ist nicht empfohlen .

Unter Berücksichtigung vonMVCsollte die Mapping-Logik in der Modellklasse implementiert werden.

@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

Verwendet:

NSDictionary *modelObjDict = [modelObj dictionary];
0
PANKAJ VERMA

Versuche dies:

#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];
}
0
刘俊利

Sie können auch die NSObject+APObjectMapping-Kategorie verwenden, die auf GitHub verfügbar ist: https://github.com/aperechnev/APObjectMapping

Es ist ganz einfach. Beschreiben Sie einfach die Mapping-Regeln in Ihrer Klasse:

#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

Und dann können Sie Ihr Objekt ganz einfach einem Wörterbuch zuordnen:

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

Sie können Ihr Objekt auch aus dem Wörterbuch analysieren:

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

Der perfekte Weg, dies zu tun, ist die Verwendung einer Bibliothek für die Serialisierung/Deserialisierung . Viele Bibliotheken sind verfügbar, aber eine, die mir gefällt, ist JagPropertyConverter https://github.com/ jagill/JAGPropertyConverter

es kann Ihr benutzerdefiniertes Objekt in NSDictionary konvertieren und umgekehrt
unterstützt sogar die Konvertierung eines Wörterbuchs oder Arrays oder eines benutzerdefinierten Objekts in Ihrem Objekt (d. h. Komposition)

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];
0
M.Shuaib Imran

Versuchen Sie es mit 

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

Und vergleichen Sie, was das Wörterbuch enthält. Versuchen Sie dann, es in JSON zu konvertieren. Schauen Sie sich die JSON-Spezifikation an. Welche Datentypen können in eine JSON-codierte Datei aufgenommen werden?

0
Wain