objective-c - the - swift 4 enum string
Conversión de NSObject a NSDictionary (9)
Como dijo mmackh, quiere definir un método personalizado para su objeto ProductDetails
que devolverá una simple NSDictionary
de valores, por ejemplo:
@implementation ProductDetails
- (id)jsonObject
{
return @{@"name" : self.name,
@"color" : self.color,
@"quantity" : @(self.quantity)};
}
...
Supongamos que añadimos propiedad del manufacturer
a nuestros ProductDetails
, que hacen referencia a una clase ManufacturerDetails
. También escribiríamos un jsonObject
para esa clase:
@implementation ManufacturerDetails
- (id)jsonObject
{
return @{@"name" : self.name,
@"address1" : self.address1,
@"address2" : self.address2,
@"city" : self.city,
...
@"phone" : self.phone};
}
...
Y luego cambie el jsonObject
para ProductDetails
para emplear eso, por ejemplo:
@implementation ProductDetails
- (id)jsonObject
{
return @{@"name" : self.name,
@"color" : self.color,
@"quantity" : @(self.quantity),
@"manufacturer" : [self.manufacturer jsonObject]};
}
...
Si ha anidado potencialmente objetos de colección (matrices y / o diccionarios) con objetos personalizados que desea codificar, también puede escribir un método jsonObject
para cada uno de ellos:
@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
Si hace algo como eso, ahora puede convertir matrices o diccionarios de su objeto de objetos personalizados en algo que pueda usarse para generar 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];
Si simplemente intentas guardar estos objetos en un archivo, te sugiero NSKeyedArchiver
y NSKeyedUnarchiver
. Pero si necesita generar objetos JSON para sus propias clases privadas, puede hacer algo como lo anterior podría funcionar.
Hola, soy una clase de tipo NSObject:
ProductDetails *details = [[ProductDetails alloc] init];
details.name = @"Soap1";
details.color = @"Red";
details.quantity = 4;
Quiero pasar el objeto "detalles" a un diccionario.
Yo si,
NSDictionary *dict = [NSDictionary dictionaryWithObject:details forKey:@"details"];
Estoy pasando este dict a otro método que realiza un control en JSONSerialization:
if(![NSJSONSerialization isValidJSONObject:dict])
Y estoy recibiendo un choque en este cheque. ¿Estoy haciendo algo mal aquí? Sé que los detalles que obtengo son un objeto JSON y lo estoy asignando a las propiedades en mi clase ProductDetails.
Por favor, ayúdame. Soy un novato en Objective-C.
Ahora intenté:
NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:(NSData*)details options:kNilOptions error:&error];
Todo lo que necesito aquí es una forma fácil de convertir detalles a NSData.
Me di cuenta de que tengo una matriz dentro de mi objeto, por eso todas las formas en que lo intenté es arrojar una excepción. Sin embargo, dado que esta pregunta se está volviendo cada vez más grande, he comenzado un hilo de pregunta para el que he mostrado los datos que obtengo dentro del objeto - https://stackoverflow.com/questions/19081104/convert-nsobject-to-nsdictionary
Intenta usar
NSDictionary *dict = [details valuesForAttributes:@[@"name", @"color"]];
Y compara lo que contiene el diccionario. Luego intente convertirlo a JSON. Y mire la especificación JSON: ¿qué tipos de datos pueden entrar en un archivo codificado JSON?
La forma perfecta de hacerlo es mediante el uso de una biblioteca para la serialización / deserialización. Hay muchas bibliotecas disponibles, pero una que me gusta es JagPropertyConverter https://github.com/jagill/JAGPropertyConverter.
puede convertir su objeto personalizado en NSDictionary y viceversa
incluso es compatible para convertir diccionario o matriz o cualquier objeto personalizado dentro de su objeto (es decir, Composición)
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];
También puede usar la categoría NSObject+APObjectMapping
que está disponible en GitHub: https://github.com/aperechnev/APObjectMapping
Es fácil de dejar. Simplemente describa las reglas de mapeo en su clase:
#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
Y luego puedes mapear fácilmente tu objeto al diccionario:
MyCustomClass * myObj = [[MyCustomClass alloc] init];
myObj.someNumber = @1;
myObj.someString = @"some string";
NSDictionary * myDict = [myObj mapToDictionary];
También puedes analizar tu objeto del diccionario:
NSDictionary * myDict = @{ @"some_number": @123,
@"some_string": @"some string" };
MyCustomClass * myObj = [[MyCustomClass alloc] initWithDictionary:myDict];
En archivo .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
en archivo .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
si se produce un bloqueo, usted verifica la propiedad (NSMutableArray, NSString, etc.) en otra condición if for for .
En tu controlador, en cualquier 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);
}
}
Puedes probar el manto, Mantle hace que sea fácil escribir una capa de modelo simple para tu aplicación. manto
Esta bien puede ser la forma más fácil de lograrlo. Importa #import <objc/runtime.h>
en tu archivo de clase.
#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];
}
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];
}
Fuente de la segunda parte: Generar cadena JSON desde NSDictionary en iOS
Puede convertir un objeto (digamos modeloObjeto) en un diccionario en tiempo de ejecución con la ayuda de la clase objc / runtime.h pero eso tiene ciertas limitaciones y no es recomendable .
Considerando MVC , la lógica de mapeo debería implementarse en la clase Modelo.
@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
Usos:
NSDictionary *modelObjDict = [modelObj dictionary];