Errore con NSJSONSerialization – Tipo non valido nella scrittura JSON (Menu)

Ho un’app che utilizza i dati principali con 3 entity framework con attributi molto simili. La relazione è come:

Filiale – >> Menu – >> Categoria – >> FoodItem

Ogni quadro ha una class associata: esempio

inserisci la descrizione dell'immagine qui

Sto cercando di generare la rappresentazione JSON dei dati nel database sqlite.

//gets a single menu record which has some categories and each of these have some food items id obj = [NSArray arrayWithObject:[[DataStore singleton] getHomeMenu]]; NSError *err; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:obj options:NSJSONWritingPrettyPrinted error:&err]; NSLog(@"JSON = %@", [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]); 

Ma invece di JSON, ottengo un errore SIGABRT.

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

Qualche idea su come risolverlo o come rendere le serializzazioni JSON (Branch, Menu, ecc.) Compatibili con la serializzazione JSON?

Questo perché la tua class “Menu” non è serializzabile in JSON. Bascially il linguaggio non sa come il tuo object dovrebbe essere rappresentato in JSON (quali campi includere, come rappresentare riferimenti ad altri oggetti …)

Dal riferimento alla class NSJSONSerialization

Un object che può essere convertito in JSON deve avere le seguenti proprietà:

  • L’object di livello superiore è un NSArray o NSDictionary.
  • Tutti gli oggetti sono istanze di NSString, NSNumber, NSArray, NSDictionary o NSNull.
  • Tutte le chiavi del dizionario sono istanze di NSString.
  • I numeri non sono NaN o infinito.

Ciò significa che la lingua sa come serializzare i dizionari. Quindi, un modo semplice per ottenere una rappresentazione JSON dal tuo menu è fornire una rappresentazione del dizionario delle istanze Menu, che verranno serializzate in JSON:

 - (NSDictionary *)dictionaryFromMenu:(Menu)menu { [NSDictionary dictionaryWithObjectsAndKeys:[menu.dateUpdated description],@"dateUpdated", menu.categoryId, @"categoryId", //... add all the Menu properties you want to include here nil]; } 

E potresti usarlo in questo modo:

 NSDictionary *menuDictionary = [self dictionaryFromMenu:[[DataStore singleton] getHomeMenu]]; NSError *err; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:menuDictionary options:NSJSONWritingPrettyPrinted error:&err]; NSLog(@"JSON = %@", [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]); 

C’è un metodo di class isValidJSONObject su NSJSONSerialization che ti dice se un object può essere serializzato. Come ha sottolineato Julien, probabilmente devi convertire il tuo object in un NSDictionary . NSManagedModel fornisce alcuni metodi utili per ottenere tutti i tuoi attributi per la tua quadro. Quindi è ansible creare una categoria per NSManagedObject che ha un metodo per convertirlo in un NSDictionary . In questo modo non è necessario scrivere un metodo toDictionary per ogni quadro che si desidera convertire in un dizionario.

 @implementation NSManagedObject (JSON) - (NSDictionary *)toDictionary { NSArray *attributes = [[self.entity attributesByName] allKeys]; NSDictionary *dict = [self dictionaryWithValuesForKeys:attributes]; return dict; } 

Puoi usare + isValidJSONObject: metodo della class NSJSONSerialization. Se non è valido, puoi usare – initWithData: encoding: method of NSString.

 - (NSString *)prettyPrintedJson:(id)jsonObject { NSData *jsonData; if ([NSJSONSerialization isValidJSONObject:jsonObject]) { NSError *error; jsonData = [NSJSONSerialization dataWithJSONObject:jsonObject options:NSJSONWritingPrettyPrinted error:&error]; if (error) { return nil; } } else { jsonData = jsonObject; } return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; } 

Ho cambiato la chiave con il valore: @ {valore: @ “chiave”} Dovrebbe essere @ {@ “chiave”: valore}