wake-up-neo.com

Fehler bei NSJSONSerialization - Ungültiger Typ beim JSON-Schreiben (Menü)

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

enter image description here

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? 

50
Vaibhav Garg

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]);
81
Julien

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;
}
24
Edward Huynh

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];
}
1
Fatih Aksu

Ich hatte den Schlüssel mit dem Wert umgestellt: @ {value: @ "key"} Es sollte @ {@ "key": value} sein.

0
jonypz