Ich habe eine App, die Kerndaten mit 3 Entitäten mit sehr ähnlichen Attributen verwendet. Die Beziehung ist wie:
Branche - >> Menü - >> Kategorie - >> FoodItem
Jede Entität hat eine zugeordnete Klasse: Beispiel
Ich versuche, eine JSON-Darstellung der Daten in der SQLite-Datenbank zu generieren.
//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]);
Aber anstelle von JSON bekomme ich einen SIGABRT-Fehler.
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid type in JSON write (Menu)'
Irgendwelche Ideen, wie man das Problem beheben kann oder wie die Entitätsklassen (Branch, Menu usw.) mit der JSON-Serialisierung kompatibel sind?
Das liegt daran, dass Ihre "Menu" -Klasse in JSON nicht serialisierbar ist. Grundsätzlich weiß die Sprache nicht, wie Ihr Objekt in JSON dargestellt werden soll (welche Felder sollen enthalten sein, wie Verweise auf andere Objekte dargestellt werden sollen ...)
Aus der NSJSONSerialization-Klassenreferenz
Ein Objekt, das in JSON konvertiert werden kann, muss folgende Eigenschaften:
- Das Objekt der obersten Ebene ist ein NSArray oder NSDictionary.
- Alle Objekte sind Instanzen von NSString, NSNumber, NSArray, NSDictionary oder NSNull.
- Alle Wörterbuchschlüssel sind Instanzen von NSString.
- Zahlen sind nicht NaN oder unendlich.
Dies bedeutet, dass die Sprache Wörterbücher serialisieren kann. Eine einfache Möglichkeit, eine JSON-Darstellung aus Ihrem Menü zu erhalten, besteht darin, eine Dictionary-Darstellung Ihrer Menü-Instanzen bereitzustellen, die Sie anschließend in JSON serialisieren:
- (NSDictionary *)dictionaryFromMenu:(Menu)menu {
[NSDictionary dictionaryWithObjectsAndKeys:[menu.dateUpdated description],@"dateUpdated",
menu.categoryId, @"categoryId",
//... add all the Menu properties you want to include here
nil];
}
Und du könntest es so verwenden:
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]);
Es gibt eine Klassenmethode isValidJSONObject
in NSJSONSerialization
, die Ihnen mitteilt, ob ein Objekt serialisiert werden kann. Wie Julien darauf hinweist, müssen Sie Ihr Objekt wahrscheinlich in eine NSDictionary
konvertieren. NSManagedModel
bietet einige praktische Methoden zum Abrufen aller Attribute für Ihre Entität. Sie könnten also eine Kategorie für NSManagedObject
erstellen, die eine Methode hat, um sie in eine NSDictionary
zu konvertieren. Auf diese Weise müssen Sie keine toDictionary
-Methode für jede Entität schreiben, die Sie in ein Wörterbuch konvertieren möchten.
@implementation NSManagedObject (JSON)
- (NSDictionary *)toDictionary
{
NSArray *attributes = [[self.entity attributesByName] allKeys];
NSDictionary *dict = [self dictionaryWithValuesForKeys:attributes];
return dict;
}
Sie können die Methode + isValidJSONObject: der Klasse NSJSONSerialization verwenden. Wenn es nicht gültig ist, können Sie - initWithData: coding: Methode von NSString verwenden.
- (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];
}
Ich hatte den Schlüssel mit dem Wert umgestellt: @ {value: @ "key"} Es sollte @ {@ "key": value} sein.