Alexey Savchenko
Alexey Savchenko

Reputation: 890

Cannot serializing sorted dictionary to JSON - Swift 3

Cannot serialize my sorted dictionary into JSON via JSONSerialization.data(withJSONObject:options:)

Serialization works with unsorted dictionary, but with sorted app throws error with description:

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

Here is how my method looks like:

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

It is interesting that in inspector while debugging unsorted dictionary looks like this: unsorted dictionary and sorted looks like this sorted dictionary

Please help in solving this issue.

Upvotes: 0

Views: 1338

Answers (1)

Rob Napier
Rob Napier

Reputation: 299355

First, there are no sorted directories in Swift stdlib (or in JSON for that matter; JSON objects are unordered). When you call .sorted() on a dictionary, it returns an array of key/value pairs [(Key, Value)].

JSONSerialization has rules about what it can serialize:

  • The top level object is an NSArray or NSDictionary.

  • All objects are instances of NSString, NSNumber, NSArray, NSDictionary, or NSNull.

  • All dictionary keys are instances of NSString.

  • Numbers are not NaN or infinity.

There are implicit bridges from NS-compatible collections to their NS equivalent, but you only get this if the contents can be expressed in ObjC (and (Key, Value) can't be).

How to implement this correctly depends heavily on the type and contents of tempDictionaryForJsonFile which aren't given here. It also depends on what you're trying to achieve with a "sorted dictionary" (which doesn't exist in JSON, so there's no way to get to it from Swift). If you mean "an ordered array of JSON objects, each with one key/value," that can be built (but you'll need to support it in whatever is consuming this data).

Upvotes: 1

Related Questions