2013-04-16 30 views
6

Bir hiyerarşide birden çok sözlükte kaydettiğim nesnelleştirilmiş bir JSON yapısını yazdırmaya çalışıyorum. Bunu NSObject'in description yöntemiyle yapmak istiyorum, böylece her bir iç içe sözlük'ün açıklama yöntemi de değerini döndürmeye çağırılıyor.İç içe NSDictionary Açıklama Kaçış Karakter Sorunları

İstenilen Sonucu Ancak

 //First Hierarchal Level 
       //Second Hierarchal Level 
         //Third Hierarchal Level 
People = 
(
    { 
     Name = Person 1 
     Gender = Male 
     Addresses = 
     ( 
      { 
       Address Name = Home Address 
       Street = 123 Street St. 
       City = NewCity 
       State = AZ 
       Zip = 12345 
       Country = USA 
      } 
     ) 
     Cars = 
     ( 
      { 
       Make = Ford 
       Model = NewFord 
       Insured Drivers = 
       (
        { 
         Name = Person 1 
        }, 
        { 
         Name = Person 2 
        } 
       ) 
      } 
     ) 
    } 
) 

//NOTE: Sample untested nested structure 

, ben her iç içe sözlük için dönüş dize dönüş dize geçirilir alır hiyerarşi her seviye için bir kez kaçtı oluyor dair bir sorunla çalışan edilmiştir. Bu açıklama nedeniyle bile sistem uygulaması gibi bir şey kullanarak bu kaçış karakterleri ekler nasıl bir ilgisi olduğunu okudum

People = \n (\n {\n Name = Person 1\\\n Gender = Male\\\n Addresses =\\\n (\\\n {\\\n Address Name = Home Address\\\n Street = 123 Street St.\\\n City = NewCity\\\n State = AZ\\\n Zip = 12345\\\n Country = USA\\\n }\\\n)\\\n Cars = \\\n (\\\n {\\\\\\\n Make = Ford\\\\\\\n Model = NewFord\\\\\\\n Insured Drivers = \\\\\\\n (\\\\\\\n {\\\\\\\\\\\\\n Name = Person 1\\\\\\\\\\\\\n },\\\\\\\\\\\\\n {\\\\\\\\\\\\\n Name = Person 2\\\\\\\\\\\\\n }\\\\\\\n)\\\\\\\n }\\\n) \n }\n) 

Fiili Sonucu, ancak ben arzu işlevselliği kullanılabilir inanıyoruz NSArray'ın içeriğini nasıl istediğim gibi açıkladığından dolayı. Sonuç dizesinde yinelemeyi ve kaçış karakterlerini ayrıştırmayı denedim ancak şu ana kadar ortaya koyduğum en iyi sonuç, tüm sözlüklerdeki tüm özelliklerin hiyerarşik olmayan bir listesidir.

Ben başkasının bu soruna rastlamak eğer merak buna nasıl üstesinden edildi

People = 
(
{ 
Name = Person 1 
Gender = Male 
Addresses = 
( 
{ 
Address Name = Home Address 
Street = 123 Street St. 
City = NewCity 
State = AZ 
Zip = 12345 
Country = USA 
} 
) 
Cars = 
( 
{ 
Make = Ford 
Model = NewFord 
Insured Drivers = 
(
{ 
Name = Person 1 
}, 
{ 
Name = Person 2 
} 
) 
} 
) 
} 
) 

En girişimi.

Her türlü öneri hoş geldiniz. Baktığınız için teşekkür ederiz.

GÜNCELLEME 1: Açıklamalarda tavsiye gereğince , şu NSDictionary kategori yöntemi kullanarak baskı için JSON dizeleri benim Sözlük nesneleri ayrıştırma denedi: bir her düzeyinde,

-(NSString*)JSONDescription 
{ 
    NSError *error; 
    NSData* jsonData = [NSJSONSerialization dataWithJSONObject:self options:NSJSONWritingPrettyPrinted error:&error]; 
    NSString* json = nil; 

    if (! jsonData) { 
     NSLog(@"WARNING: NSDictionary JSONDescription encountered error \"%@\"", error); 
    } else { 
     json = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; 
    } 

    return json; 
} 

Sonra benim hiyerarşi, her description yönteminde sözlük nesnesinin JSONDescription aramasını yapıyorum. Ancak, yuvalanmış nesnenin description yönteminin çağrıldığı görünmüyor. Bu aşağıdaki istisna neden olan:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid type in JSON write (Address)' 

Örnek Uygulama

#import "Person.h" 

#define NAME @"Name" 
#define GENDER @"Gender" 
#define ADDRESSES @"Addresses" 
#define CARS @"Cars" 

@implementation Person 

-(NSDictionary*)toDictionary{ 
    return @{ NAME: self.name, 
       GENDER: self.gender, 
       ADDRESSES: self.addresses, 
       CARS: self.cars}; 
} 

-(NSString*)description{ 
    return self.toDictionary.JSONDescription; 
} 

@end 


#import "Address.h" 

#define ADDRESS_NAME @"Address Name" 
#define STREET @"Street" 
#define CITY @"City" 
#define STATE @"State" 
#define ZIP @"Zip" 
#define COUNTRY @"Country" 

@implementation Address 

-(NSDictionary*)toDictionary{ 
    return @{ ADDRESS_NAME: self.addressName, 
       STREET: self.street, 
       CITY: self.city, 
       STATE: self.state, 
       ZIP: self.zip, 
       COUNTRY: self.country}; 
} 

-(NSString*)description{ 
    return self.toDictionary.JSONDescription; 
} 

@end 


#import "Car.h" 

#define MAKE @"Make" 
#define MODEL @"Model" 
#define INSURED_DRIVERS @"Insured Drivers" 

@implementation Car 

-(NSDictionary*)toDictionary{ 
    return @{ MAKE: self.make, 
       MODEL: self.model, 
       INSURED_DRIVERS: self.drivers}; 
} 

-(NSString*)description{ 
    return self.toDictionary.JSONDescription; 
} 

@end 


#import "Driver.h" 

#define NAME @"Name" 

@implementation Car 

-(NSDictionary*)toDictionary{ 
    return @{ NAME: self.name}; 
} 

-(NSString*)description{ 
    return self.toDictionary.JSONDescription; 
} 

@end 
+0

ben bazen (sözlükten gibi) "key = value" ve bazen de gösterdiği için biraz karıştı.Çıktıda hangisini istiyorsunuz? - Ve "en iyi girişimi" üreten kodunuzu gösterebilir misiniz? –

+0

Ah evet. Teşekkürler. Örneği düzelttim. Elbette ister istemez, ister istemez çıktısını almak isterim. Yeni satırların girintilemesine ve yazdırılmasına, eşittir veya iki nokta üst üste yazıyorsa, endişelendiğimden daha fazla endişeleniyorum. – Krejko

+0

Ne yazık ki, artık kod benim en iyi denemeye sahip değil ama birkaç farklı [myDescriptionString stringByReplacingOccurrencesOfString: @ "\\" withString: @ "\"] ve eklenen tüm kaçan karakterleri kaldı. . Girintiye nasıl düzgün bir şekilde ekleneceğini anlayamadım. – Krejko

cevap

5

aşağıdaki yöntem en zarif olmayabilir, ancak istenilen çıktıyı üretmek gibi görünüyor:

@interface NSObject (MyPrettyPrint) 
- (NSString *)prettyPrint; 
@end 

// === ADDED CODE FOR CUSTOM OBJECTS (1) === 
@protocol ObjectToDictionary <NSObject> 
-(NSDictionary *)toDictionary; 
@end 
// === END OF ADDED CODE (1) === 

@implementation NSObject (MyPrettyPrint) 

- (NSString *)prettyPrint 
{ 
    BOOL isColl; 
    return [self prettyPrintAtLevel:0 isCollection:&isColl]; 
} 

- (NSString *)prettyPrintAtLevel:(int)level isCollection:(BOOL *)isCollection; 
{ 

// === ADDED CODE FOR CUSTOM OBJECTS (2) === 
    if ([self respondsToSelector:@selector(toDictionary)]) { 
     NSDictionary *dict = [(id <ObjectToDictionary>)self toDictionary]; 
     return [dict prettyPrintAtLevel:level isCollection:isCollection]; 
    } 
// === END OF ADDED CODE (2) === 

    NSString *padding = [@"" stringByPaddingToLength:level withString:@" " startingAtIndex:0]; 
    NSMutableString *desc = [NSMutableString string]; 

    if ([self isKindOfClass:[NSArray class]]) { 
     NSArray *array = (NSArray *)self; 
     NSUInteger cnt = [array count]; 
     [desc appendFormat:@"%@(\n", padding]; 
     for (id elem in array) { 
      BOOL isColl; 
      NSString *s = [elem prettyPrintAtLevel:(level+3) isCollection:&isColl]; 
      if (isColl) { 
       [desc appendFormat:@"%@", s]; 
      } else { 
       [desc appendFormat:@"%@ %@", padding, s]; 
      } 
      if (--cnt > 0) 
       [desc appendString:@","]; 
      [desc appendString:@"\n"]; 
     } 
     [desc appendFormat:@"%@)", padding ]; 
     *isCollection = YES; 

    } else if ([self isKindOfClass:[NSDictionary class]]) { 
     NSDictionary *dict = (NSDictionary *)self; 
     [desc appendFormat:@"%@{\n", padding]; 
     for (id key in dict) { 
      BOOL isColl; 
      id value = dict[key]; 
      NSString *s = [value prettyPrintAtLevel:(level+3) isCollection:&isColl]; 
      if (isColl) { 
       [desc appendFormat:@" %@%@ =\n%@\n", padding, key, s]; 
      } else { 
       [desc appendFormat:@" %@%@ = %@\n", padding, key, s]; 
      } 
     } 
     [desc appendFormat:@"%@}", padding ]; 
     *isCollection = YES; 

    } else { 
     [desc appendFormat:@"%@", self]; 
     *isCollection = NO; 
    } 

    return desc; 
} 

Örnek:

NSDictionary *dict = @{@"People": @[ 
    @{ 
     @"Name": @"Person 1", 
     @"Gender": @"Male", 
     @"Addresses": @[ 
      @{ 
       @"Address Name": @"Home Address", 
       @"Street": @"123 Street St.", 
       @"Zip": @12345 
      }, 
     ], 
     @"Cars": @[ 
      @{ 
       @"Make": @"Ford", 
       @"Model": @"NewFord", 
       @"Insured Drivers": @[ 
        @{@"Name": @"Person 1"}, 
        @{@"Name": @"Person 2"}, 
       ] 
      }, 
     ], 
    }, 

]}; 

NSLog(@"People =\n%@", [dict[@"People"] prettyPrint]); 

Çıktı: En örneklerde (JSON olduğu gibi): "değerini tuşu"

 
People = 
(
    { 
     Name = Person 1 
     Gender = Male 
     Cars = 
     (
     { 
      Model = NewFord 
      Make = Ford 
      Insured Drivers = 
      (
       { 
        Name = Person 1 
       }, 
       { 
        Name = Person 2 
       } 
      ) 
     } 
    ) 
     Addresses = 
     (
     { 
      Zip = 12345 
      Address Name = Home Address 
      Street = 123 Street St. 
     } 
    ) 
    } 
) 
+0

Bu, şu anda sahip olduğum çözümün çok yakınında. Bununla birlikte, benim örneğime uygulandığında, her bir nesneyi açıklama olarak kendisinin sözlük değerini yaratırken, her satır, girintinin ilk seviyesinde. Bu, çıktıyı, en iyi denemem olarak listelediğim cevaba neredeyse aynıyor. Cevabınız için teşekkürler, daha yakınlaştığımızı hissediyorum! – Krejko

+0

Nesne hiyerarşisinin her katmanının, yazdırılmak üzere kendi başına bir sözlük temsili oluşturması gerekir. Aksi halde JSON'umdan ayrıştırılan veriler bu nesnelerdeki özelliklerde saklanır. Bu formatta, nesne kolayca yazdırılamaz. Bu nesnelere kolayca basılabilmeye çalışmam, bu değerleri bir sözlüğüne önbelleğe almayı ve sözlüğü açıklamaya yazdırmayı içeriyordu. Bunu yapmanın daha iyi bir yolunun farkındaysanız lütfen bana bildirin. – Krejko

+0

@Krejko: Daha önce görmedim ki, "Araba", "Adres" vb özel nesneleriniz var. Yöntemim, NSJSONSerialization'dan aldığınız tam sözlükte uygulanacaktı. –