0

So, I keep getting the error below when I attempt to do a JSONSerialization on a JSON object I download for an app I'm building. Basically, what I've done is I create a JSON file, save it on SugarSync, and get the direct download link to download and use in my program. Sort of my own bootleg API.

I know it downloads because if I convert the file to a string using the URL, it prints out the file. The problem is that I can't get past this error.

Error Domain=NSCocoaErrorDomain Code=3840 "No string key for value in object around character 2."

This is an example of how the file reads (super simple!):

    {"buddy": "pal", 
    "brother": "bear"}

I've tried changing to NSData instead of Data, but that creates more problems. Tried doing an NSDictionary on the JSONSerialization line, but that threw more errors. I also tried .mutableContainers, also to no avail.

Below is the whole code, including the SugarSync file URL in order of you to recreate the error yourself. I don't understand what I'm doing wrong, and if anyone can help, that would be amazing.

Thank you!

    // Create destination URL
    let documentsURL: URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first as URL!
    let destinationFileUrl = documentsURL.appendingPathComponent("downloadedFile.json")

    // Create URL to the source file you want to download
    let fileURL = URL(string: "https://www.sugarsync.com/pf/D7126167_796_275761334?directDownload=true")

    let sessionConfig = URLSessionConfiguration.default
    let session = URLSession(configuration: sessionConfig)

    let request = URLRequest(url: fileURL!)

    let task = session.downloadTask(with: request) { (tempLocalUrl, response, error) in
        if let tempLocalUrl = tempLocalUrl, error == nil {

            // Success
            if let statusCode = (response as? HTTPURLResponse)?.statusCode {
                print("Successfully downloaded. Status code: \(statusCode)")

            }

            do {
                print("move files")
                try FileManager.default.copyItem(at: tempLocalUrl, to: destinationFileUrl)

                let fileData: Data = try Data(contentsOf: destinationFileUrl, options: Data.ReadingOptions.mappedIfSafe)

                print(fileData)

                let myJson = try JSONSerialization.jsonObject(with: fileData, options: []) as? [[String: Any]]

                print(myJson!)

                do {
                    // This converts the file into String and is printed (doesn't get to this because of the error, but it works!)
                    let jsonText = try String(contentsOf: tempLocalUrl, encoding: String.Encoding.utf8)
                    print(jsonText)


                } catch {
                    print("failed to print json file")
                }


            } catch (let writeError) {
                print("Error creating a file \(destinationFileUrl) : \(writeError)")

            }
        } else {
            print("Error took place while downloading file. Error description: %@", error?.localizedDescription ?? "unknown")
        }
    }
    task.resume()

EDIT --------------------------- It looks like the serialization is very sensitive. It needs something like this to work:

    {"widget": {
"debug": "on",
"window": {
    "title": "Sample Konfabulator Widget",
    "name": "main_window",
    "width": 500,
    "height": 500
},
"image": { 
    "src": "Images/Sun.png",
    "name": "sun1",
    "hOffset": 250,
    "vOffset": 250,
    "alignment": "center"
},
"text": {
    "data": "Click Here",
    "size": 36,
    "style": "bold",
    "name": "text1",
    "hOffset": 250,
    "vOffset": 100,
    "alignment": "center",
    "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
}
}}  

But this one won't work:

    {“website”: {
“iPhone”: {
    “blogURL”: ”string”,
    “blogHead”: “string”,
    “reportURL”: “string”,
    “reportHead”: “string”
}
}}

Note: this website is not showing the JSON indentations properly. This is where I'm getting my JSON examples.

Bennybear
  • 335
  • 2
  • 13

2 Answers2

2

You're trying to parse a JSON that is of type [[String: Any]], when the JSON is simply just a dictionary ([String: Any]) not an array of dictionaries.

Try changing to this:

let myJson = try JSONSerialization.jsonObject(with: fileData, options: []) as? [String: Any]
Benjamin Lowry
  • 3,730
  • 1
  • 23
  • 27
  • Thanks for the reply! I'll give it a shot when I get home later today, although I think I've tried that as well. I'll let you know later today. Hope it works! Thanks, again! – Bennybear Jan 30 '17 at 20:15
  • Unfortunately, that didn't work. Too bad. Even made a few changes to the JSON doc to see if it was that, but it's not. – Bennybear Jan 30 '17 at 23:39
0

It worked out in the end. It turns out, as I stated in my edit, that the json serializer is very sensitive. So, I decided to use this JSON online editor to make sure that everything I need is absolutely correct, including the right font and size, etc.

Bennybear
  • 335
  • 2
  • 13