Подтвердить что ты не робот

Ошибка с NSJSONSerialization - Недопустимый тип записи JSON (меню)

У меня есть приложение, использующее основные данные с 3 объектами с очень похожими атрибутами. Связь такова:

Отрасль → > Меню → > Категория → > FoodItem

Каждый объект имеет ассоциированный класс: example

enter image description here

Я пытаюсь создать JSON-представление данных в базе данных 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]);

Но вместо JSON я получаю ошибку SIGABRT.

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

Любые идеи, как это исправить или как сделать классы сущностей (Branch, Menu и т.д.) совместимыми с JSON-сериализацией?

4b9b3361

Ответ 1

Это потому, что ваш класс "Меню" не сериализуется в JSON. Bascially язык не знает, как ваш объект должен быть представлен в JSON (какие поля включать, как представлять ссылки на другие объекты...)

Из Справка класса NSJSONSerialization

Объект, который может быть преобразован в JSON, должен иметь следующее Свойства:

  • Объект верхнего уровня - NSArray или NSDictionary.
  • Все объекты являются экземплярами NSString, NSNumber, NSArray, NSDictionary или NSNull.
  • Все словарные ключи являются экземплярами NSString.
  • Числа не NaN или бесконечность.

Это означает, что язык знает, как сериализовать словари. Таким образом, простой способ получить представление JSON из вашего меню - предоставить представление в виде словаря ваших экземпляров меню, которое затем будет сериализоваться в 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];
}

И вы можете использовать его так:

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

Ответ 2

Существует метод класса isValidJSONObject на NSJSONSerialization, который сообщает вам, может ли объект быть сериализован. Как указал Жюльен, вам, вероятно, придется преобразовать свой объект в NSDictionary. NSManagedModel предоставляет некоторые удобные методы для получения всех ваших атрибутов для вашего объекта. Таким образом, вы можете создать категорию для NSManagedObject, у которой есть способ ее преобразования в NSDictionary. Таким образом, вам не нужно писать метод toDictionary для каждого объекта, который вы хотите преобразовать в словарь.

@implementation NSManagedObject (JSON)

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

Ответ 3

Вы можете использовать + isValidJSONObject: метод класса NSJSONSerialization. Если это недопустимо, вы можете использовать - initWithData: encoding: метод 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];
}

Ответ 4

У меня был ключ, переключенный со значением: @{значение: @ "key" } Это должно быть @{@ "ключ": значение}