J'ai une application utilisant des données de base avec 3 entités avec des attributs très similaires. La relation est telle que:
Succursale - >> Menu - >> Catégorie - >> FoodItem
Chaque entité a une classe associée: exemple
J'essaie de générer une représentation JSON des données dans la base de données 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]);
Mais au lieu de JSON, je reçois une erreur SIGABRT.
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid type in JSON write (Menu)'
Des idées pour résoudre ce problème ou pour rendre les classes d'entités (branche, menu, etc.) compatibles avec la sérialisation JSON?
En effet, votre classe "Menu" n'est pas sérialisable en JSON. En gros, le langage ne sait pas comment votre objet doit être représenté en JSON (quels champs inclure, comment représenter les références à d'autres objets ...)
Depuis la référence de la classe NSJSONSerialization
Un objet pouvant être converti en JSON doit avoir le suivant Propriétés:
- L'objet de niveau supérieur est un NSArray ou NSDictionary.
- Tous les objets sont des instances de NSString, NSNumber, NSArray, NSDictionary ou NSNull.
- Toutes les clés de dictionnaire sont des instances de NSString.
- Les nombres ne sont ni NaN ni l'infini.
Cela signifie que la langue sait sérialiser les dictionnaires. Ainsi, un moyen simple d'obtenir une représentation JSON à partir de votre menu consiste à fournir une représentation de dictionnaire de vos instances de menu, que vous allez ensuite sérialiser en 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];
}
Et vous pourriez l'utiliser comme ceci:
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]);
Il existe une méthode de classe isValidJSONObject
sur NSJSONSerialization
qui vous indique si un objet peut être sérialisé. Comme Julien l'a souligné, vous devez probablement convertir votre objet en un NSDictionary
. NSManagedModel
fournit des méthodes pratiques pour obtenir tous vos attributs pour votre entité. Vous pouvez donc créer une catégorie pour NSManagedObject
avec une méthode pour la convertir en NSDictionary
. Ainsi, vous n'avez pas besoin d'écrire une méthode toDictionary
pour chaque entité que vous souhaitez convertir en dictionnaire.
@implementation NSManagedObject (JSON)
- (NSDictionary *)toDictionary
{
NSArray *attributes = [[self.entity attributesByName] allKeys];
NSDictionary *dict = [self dictionaryWithValuesForKeys:attributes];
return dict;
}
Vous pouvez utiliser la méthode + isValidJSONObject: de la classe NSJSONSerialization. Si ce n'est pas valide, vous pouvez utiliser - 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];
}
La clé a été commutée avec la valeur: @ {valeur: @ "clé"} Ce devrait être @ {@ "clé": valeur}