2017-01-11 6 views
0

Не может сериализовать мой отсортированный словарь в JSON с помощью JSONSerialization.data(withJSONObject:options:)Не может сериализации отсортированного словаря для JSON - Swift 3

сериализации работает с несортированным словарем, но с отсортированным приложением выбрасывает ошибку с описанием:

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

Вот как мой метод выглядит следующим образом:

func createJSONFile(){ 
    // create path to json file 
    let fileManager = FileManager.default 
    let urls = fileManager.urls(for: .documentDirectory, in: .userDomainMask) 
    let documentDirectory = urls[0] as NSURL 
    guard let jsonURL = documentDirectory.appendingPathComponent("graphData") else { 
     print("Failed to create path to json file.") 
     return 
    } 

    print(jsonURL.absoluteString) 
    // creating a .json file in the Documents folder 
    if !fileManager.fileExists(atPath: jsonURL.absoluteString){ 
     fileManager.createFile(atPath: jsonURL.absoluteString, contents: nil, attributes: nil) 
     print("file created") 
    } 

    do { 
     let unsortedDic = self.tempDictionaryForJsonFile 
     let sortedDic = unsortedDic.sorted(by: <) 
     let jsonData = try JSONSerialization.data(withJSONObject: sortedDic, options: .prettyPrinted) 
     print(jsonData) 
     try jsonData.write(to: jsonURL) 

     print(fileManager.fileExists(atPath: jsonURL.absoluteString)) 

     let content = try String.init(contentsOf: jsonURL, encoding: .utf8) 
     print(content) 

    } catch { 
     print(error.localizedDescription) 
    } 
} 

интересно, что в инспекторе при отладке несортированный словаря выглядит следующим образом: unsorted dictionary и отсортировано выглядит так sorted dictionary

Помогите решить эту проблему.

+0

'Словарь' не имеет никакого заказа. –

ответ

1

Во-первых, нет отсортированных каталогов в Swift stdlib (или в JSON, если на то пошло, объекты JSON неупорядочены). Когда вы вызываете .sorted() в словаре, он возвращает массив пар ключ/значение [(Key, Value)].

JSONSerialization имеет правила о том, что он может сериализовать:

  • Объект верхнего уровня является NSArray или NSDictionary.

  • Все объекты являются экземплярами NSString, NSNumber, NSArray, NSDictionary или NSNull.

  • Все словарные ключи являются экземплярами NSString.

  • Номера не NaN или бесконечность.

Есть неявные мосты из NS-совместимых коллекций до их NS эквивалент, но вы получите только если содержимое может быть выражено в ObjC (и (Key, Value) не может быть).

Как правильно реализовать это, в значительной степени зависит от типа и содержимого tempDictionaryForJsonFile, которые здесь не указаны. Это также зависит от того, чего вы пытаетесь достичь, с помощью «отсортированного словаря» (которого нет в JSON, поэтому нет возможности добраться до него от Swift). Если вы имеете в виду «упорядоченный массив объектов JSON, каждый с одним ключом/значением», который может быть создан (но вам нужно будет поддерживать его во всех потребляющих эти данные).

+0

Спасибо за информацию! Моя задача - иметь JSON-файл с X и Y аудиозаписью в конце. Для ясности я извлекаю частоту дискретизации из аудиофайла во время воспроизведения, а затем добавляю каждое значение частоты дискретизации в момент времени в массив [Float]. Затем я запускаю этот массив [Float] с .enumerate и создаю словарь, который представляет собой индексы массива [Float], отлитые для String, а значения - соответствующие значения массива, также отлитые от String. В конце получается, что этот выходной словарь имеет неупорядоченные ключи. –

+0

«В конце концов, этот выходной словарь имеет неупорядоченные клавиши». Верный. Все словари Swift имеют неупорядоченные ключи (и объекты JSON имеют неупорядоченные ключи). Это было как вопрос? Непонятно, почему вы конвертируете любое из этих чисел в строки; это очень странно и подвержено ошибкам (и не будет правильно сортировать, если вы хотите сортировать). Это кажется очень запутанным. Если у вас уже есть '[Float]', почему бы просто не сериализовать это? Или '[Record]', где 'Record' будет иметь время выборки, X и Y плавает? –

+0

Спасибо за ваш добрый ответ.Прежде чем вы отправили его, мне удалось сериализовать данные графа в массив [[String: Float]], где String - индекс значения Y (Float) графика, поэтому у меня есть файл JSON с содержимым типа: [ { " index ": значение }, {" index ": значение ...}. Это было частью тестовой задачи для собеседования. –