Ошибка с NSJSONSerialization - Недопустимый тип при записи JSON (Меню) - PullRequest
50 голосов
/ 27 марта 2012

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

Ветвь - >> Меню - >> Категория - >> FoodItem

У каждого объекта есть связанный класс: пример

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)'

Есть идеи, как это исправить или как совместить сериализацию JSON (ветвь, меню и т. Д.) С сериализацией?

Ответы [ 4 ]

81 голосов
/ 27 марта 2012

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

Из ссылки на класс NSJSONSerialization

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

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

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

Существует метод класса 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;
}
1 голос
/ 08 октября 2015

Вы можете использовать + 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];
}
0 голосов
/ 23 мая 2016

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...