1

So the issue I am facing is that i have two arrays in an ios app which i need to store in a remote mySQL database, which i would like to accomplish using php and json. I haven't, however, despite several days of work, managed to get the arrays in the ios app converted into json code which doesn't crash the app. The arrays are populated by a qr code reader and input field, and there is always an equal amount of items in each array. Currently the code below generates the following json:

json string = {"b":"[\n\n]","p":"[\n\n]"}

No matter what changes i do, the app seems to crash with the following error: Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** +[NSJSONSerialization dataWithJSONObject:options:error:]: Invalid top-level type in JSON write', or alternatively it says Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.} with some of my other experiments (like the version currently below)

var productArray = [String]()
var amountArray = [String]()



func addTapped(sender: UIBarButtonItem) {
    print("Running add func")
    do {
        var test1 = ""
        var test2 = ""
        //Convert to Data
        let jsonData1 = try! JSONSerialization.data(withJSONObject: amountArray, options: JSONSerialization.WritingOptions.prettyPrinted)
        let jsonData2 = try! JSONSerialization.data(withJSONObject: productArray, options: JSONSerialization.WritingOptions.prettyPrinted)

        //Convert back to string. Usually only do this for debugging
        if let JSONString1 = String(data: jsonData1, encoding: String.Encoding.utf8) {
            print(JSONString1)
            test1 = JSONString1
        }
        if let JSONString2 = String(data: jsonData2, encoding: String.Encoding.utf8) {
            print(JSONString2)
            test2 = JSONString2
        }
        //In production, you usually want to try and cast as the root data structure. Here we are casting as a dictionary. If the root object is an array cast as [AnyObject].
        var json1 = try JSONSerialization.jsonObject(with: jsonData1, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String: AnyObject]
        var json2 = try JSONSerialization.jsonObject(with: jsonData2, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String: AnyObject]






        let dict = ["json1": test1, "json2": test2] as [String: Any]


        print("All JSON should print below")
        print(dict)
        if let jsonData = try? JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted) {
            let url = NSURL(string: "http://www.server.com/receiver")!
            let request = NSMutableURLRequest(url: url as URL)
            request.httpMethod = "POST"
            request.addValue("application/json", forHTTPHeaderField: "Content-Type")
            request.httpBody = jsonData

            let task = URLSession.shared.dataTask(with: request as URLRequest){ data,response,error in
                if error != nil{
                    print(error?.localizedDescription)
                    return
                }

                do {
                    let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary

                    if let parseJSON = json {
                        let resultValue:String = parseJSON["success"] as! String;
                        print("result: \(resultValue)")
                        print(parseJSON)
                    }
                } catch let error as NSError {
                    print(error)
                }        
            }          
            task.resume()
        }


    } catch {
        print("Oops")
    }

}
  • in which line your code stopped ? – KKRocks May 05 '17 at 05:56
  • @KKRocks That's part of my issue - XCode thinks that information is unnecessary despite having zombie objects enabled, so it doesn't tell me that. – Rasmus Karlsson May 05 '17 at 05:59
  • set exception breakpoint and run code again : http://stackoverflow.com/a/17802868/3901620 – KKRocks May 05 '17 at 06:02
  • Noticed that one of the things i had tried to do broke the code slightly, i fixed it above (just a minor variable name issue). Now The program doesn't crash, instead it says Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.} – Rasmus Karlsson May 05 '17 at 06:20
  • if let jsonData = try? JSONSerialization.data(withJSONObject: dict, options: .allowFragments) try this line – KKRocks May 05 '17 at 06:24
  • It says / Type 'JSONSerialization.WritingOptions' has no member 'allowFragments' when i try that. – Rasmus Karlsson May 05 '17 at 06:32
  • Just replace it let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary to allowFragments. you can see now the error message is diffrent – Sunil M. May 05 '17 at 07:45
  • I'm sorry, but i'm not sure what you want me to replace with that. – Rasmus Karlsson May 05 '17 at 08:12

1 Answers1

1

I think the best solution is using SwiftyJSON

Whit that, if you have a String you can use var json = JSON.parse(yourString)

David Luque
  • 1,078
  • 5
  • 18
  • 30