JSON from file Swift 3.0 do not work - json

I have a problem with JSON, I want to read file JsonData.json using that code(I traied many ways), and always get that error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** +[NSJSONSerialization dataWithJSONObject:options:error:]: Invalid top-level type in JSON write'
Someone can help me?
func readPropertyList(){
if let path = Bundle.main.path(forResource:"JsonData", ofType: "json"){
//if let url = Bundle.main.url(forResource:"JsonData", withExtension: "json") {
let url: URL = URL(fileURLWithPath: path)
do {
let data: Data = try! Data(contentsOf: url , options: .alwaysMapped)
//let swiftDictionary = try PropertyListSerialization.propertyList(from: data, options: [], format: nil) as! [String]
//list = swiftDictionary
let thisJSON = try! JSONSerialization.data(withJSONObject: data, options: [] )
print(thisJSON)
//print(list)
} catch {
print("lol")
}
}
}
Maybe my, JSON file is wrong but I try verify on http://jsonlint.com and that page say is fine.
{
"Eng":
[
{"Food":
[
{"Avilable":true,
"Meat":
[
{
"Meat":"Mięso",
"Poultry":"Drób",
"Turkey":"Indyk",
"Chicken":"Kurczak",
"Veal":"Cięcina",
"Mutton":"Baranina",
"Venison":"Sarnina",
"Pork":"Wieprzowina",
"Beef":"Wołowina",
"Lamb":"Jagnięcina"
}
],
"Fish":
[
{
"Fish":"ryba",
"Sea food":"Owoce morza",
"Shrimps":"Krewetki",
"Prawns":"Krewetki",
"Mussels":"Małże",
"Crayfish":"Rak słodkowodny",
"Lobster":"Homar",
"Crab":"Krab",
"Tuna":"Tuńczyk",
"Crap":"Karp",
"Eel":"W\u0119gorz",
"Sardine":"Sardynka",
"Salmon":"\u0141oso\u015b",
"Herring":"\u015aled\u017a",
"Cod":"Dorsz",
"Trout":"Pstr\u0105g",
"Bass":"Oko\u0144",
"Fl\u0105dra":"Plaice",
"Pike":"Szczupak"
}
],
"Dairy":
[
{
"Dairy":"Nabia\u0142",
"Dairy products":"Produkty mleczne",
"Milk":"Mleko",
"Cheese":"Ser",
"Cheeses":"Serki",
"Cottage cheese":"Twar\u00f3g",
"Cream":"\u015amierana",
"Yoghurt":"Jogurt",
"Butter":"Mas\u0142o",
"Margarine":"Margaryna"
}
]
}
]
}
]
}

You're using the wrong API. It's the other way round
let thisJSON = try! JSONSerialization.jsonObject(with: data, options: [] )

Related

Read from API JSON using Alamofire Swift 4

i have hard time to read JSON using Alamofire. below is the structure of the API response
{
"data": [
{
"order": {
"id": 258,
"created_at": "2018-07-01T14:51:05+08:00",
"user_id": "1234"
},
"transactions": [
{
"transaction_type": "rent",
"cabinet_id": "02110A0000C6",
"jack_id": 1
}
]
}
]
}
Basically, i need to print out only the array of transactions and also print one by one the transaction_type, cabinet_id, and jack_id
The previous one i just manage to print the api response using code below
Alamofire.request(WalletRouter.urlUserActiveOrder(id: userId)).responseJSON { response in
if let value = response.result.value {
let dict = value as? Dictionary<String, AnyObject>
//print (value)
if let innerDict = dict!["data"] {
print (innerDict) //manage to return the value
let data = innerDict["transactions"] as! NSArray //get error here
print (data)
}
}
//do your json stuff
else if (response.result.isFailure) {
//Manager your error
switch (response.error!._code){
case NSURLErrorTimedOut:
//Manager your time out error
break
case NSURLErrorNotConnectedToInternet:
//Manager your not connected to internet error
break
default:
print ("error")
}
}
}
i have already spent 6 hour to solve this, but still failed to get the value.
Create a struct class like below
struct Result: Decodable {
struct data12: Decodable {
struct transaction: Decodable {
let transactionType:String
let cabinetId:String
let jackId:Int
}
let transactions:[transaction]
}
let data:[data12]
}
Data fetching like this
do {
let data1 = try Data(contentsOf: URL(fileURLWithPath: path), options: [])
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let courses = try decoder.decode(Result.self, from: data1)
print(courses)
} catch {
print(error)
}
if anyOne think my approach is wrong please update my answer TIA

How to get data from local JSON file in swift?

I want to get data from local JSON file. It's look like:
[
[
{
"link": "link1",
"answers": [
"answer1",
"answer2",
"answer3",
"answer4",
"answer5"
],
"questions": "question1"
},
{
"link": "link2",
"answers": [
"answer1",
"answer2",
"answer3",
"answer4",
"answer5"
],
"questions": "question2"
}
]
]
How can I take separately each element?
And how can I take separately each answer?
I want to use answers in table view.
indexPath.row[1] = answer1
indexPath.row[2] = answer2...
let url = Bundle.main.url(forResource: "info", withExtension: "json")!
do {
let jsonData = try Data(contentsOf: url)
let json = try JSONSerialization.jsonObject(with: jsonData)
print(json)
//let current = json["title"] as! [String: [String:Any]]
//for (key, currency) in current {
//let quest = currency["title"] as! String
//let img = currency["image"] as! String
//let ans = currency["answers"] as! [String]
//}
}
catch {
print(error)
}
}
You have to take care of the JSON structure to get the correct values. See the below snippet to see how you can reach your questions in JSON.
let url = Bundle.main.url(forResource: "File", withExtension: "txt")!
do {
let jsonData = try Data(contentsOf: url)
let json = try JSONSerialization.jsonObject(with: jsonData) as! [[[String: Any]]]
if let question1 = json.first?[0] {
print( question1["link"] as! String)
}
if let question2 = json.first?[1] {
print( question2["link"] as! String)
}
}
catch {
print(error)
}
So now, you know how to reach the actual data. You should create some Question class. Then you should retain a list of questions parsed from the file and use that list for your TableView.

Retrieving JSON elements in Swift 3

I have following JSON file
{
"events": [
{
"date": "01/11/2017",
"name": [
"Tulsi Vivah",
"Pradosh Vrat"
],
"photo": [
"photo_chaturthi",
"photo_ekadashi"
]
},
{
"date": "03/11/2017",
"name": [
"Guru Nanak Jayanti"
],
"photo": [
"photo_chaturthi",
"photo_ekadashi"
]
}
]
}
I want to parse this and put the elements in the objectArray in the code below:
struct Objects {
var sectionName : String!
var sectionObjects : [String]!
var sectionImages : [String]!
}
var objectArray = [Objects]()
I have written following code for reading the file:
if let file = Bundle.main.url(forResource: "EventsEnglish112017", withExtension: "json") {
let data = try Data(contentsOf: file)
let json = try JSONSerialization.jsonObject(with: data as Data, options: [])
My question is how do I typecast "json" to read the individual elements to fill the above objectArray.
Thanks!
A JSON is a dictionary of type [String:Any?]
To parse it:
if let dictionary = json as? [String: Any?] {
if let events = dictionary["events"] as? [[String: Any?]] {
// events is an array of JSON objects, so it's an array of dictionaries
for item in events
{
let date = item["date"] as? String // this is a String?
let name = item["name"] as? [String]
// same goes for 'photo'
}
}
}
Now that you have retrieved the data, you can use it to costruct your custom objects.
But it's better if you use some library that will make it for you, or use Swift4
To retrieve data from JSON file
(Swift 3)
if let path = NSBundle.mainBundle().pathForResource("myJson", ofType: "json")
{
if let jsonData = NSData(contentsOfFile: path, options: .DataReadingMappedIfSafe, error: nil)
{
if let jsonResult = NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers, error: nil) as? [String: Any]
{
if let eventsInfo = jsonResult["events"] as? [Any]
{
// Here you will get your data in Array format.
// for e.g
// print(eventsInfo[0]["date"])
// Just pass this eventsInfo (Array) into you Object model initializer and parse with the keys there.
}
}
}
}
(Swift 4)
if let path = Bundle.main.path(forResource: "myJson", ofType: "json") {
do {
let data = try Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe)
let jsonResult = try JSONSerialization.jsonObject(with: data, options: .mutableLeaves)
if let jsonResult = jsonResult as? Dictionary<String, AnyObject>, let eventsInfo = jsonResult["events"] as? [Any] {
// Here you will get your data in Array format.
// for e.g
// print(eventsInfo[0]["date"])
// Just pass this eventsInfo (Array) into you Object model initializer and parse with the keys there.
}
} catch {
// handle error
}
}

How to save JSON data using SwiftyJSON

I am trying to save data localy using the JSON library. Here is my code at the moment:
var jsonFile = "json.json"
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let jsonFile = "file.json"
let jsonArray:JSON = [
"array": [12.34, 56.78],
"users": [
[
"id": 987654,
"info": [
"name": "jack",
"email": "jack#gmail.com"
],
"feeds": [98833, 23443, 213239, 23232]
],
[
"id": 654321,
"info": [
"name": "jeffgukang",
"email": "jeffgukang#gmail.com"
],
"feeds": [12345, 56789, 12423, 12412]
]
]
]
if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
{
let path = dir.appendingPathComponent(jsonFile)
if(!FileManager.default.fileExists(atPath: path.path))
{
FileManager.default.createFile(atPath: path.path, contents: Data(), attributes: nil)
print("Created file")
do {
try write(json: jsonArray, to: path)
} catch let error{
print("Error: \(error.localizedDescription)")
}
try! write(json: jsonArray, to: path)
} else {
print("File existed")
do {
let myJSON = try readJSON(myURL: path)
if let _ = myJSON
{
print("Got data")
} else {
print("No Data")
}
} catch let errorOne {
print("Error2: \(errorOne.localizedDescription)")
}
}
}
}
}
let url = Bundle.main.url(forResource: "json", withExtension: "json")
func readJSON(myURL:URL) throws -> JSON? {
if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
{
let path = dir.appendingPathComponent(jsonFile)
if(!FileManager.default.fileExists(atPath: path.path))
{
let data = try Data(contentsOf: path, options: .alwaysMapped)
return JSON(data: data)
}
}
return nil
}
func write(json: JSON, to url: URL) throws {
let data = try json.rawData()
if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
{
let path = dir.appendingPathComponent(jsonFile)
if(!FileManager.default.fileExists(atPath: path.path))
{
try data.write(to: path)
}
}
}
When you run the program for the first time, it creates the file and 'writes the jsonArray'. When you run it again, it 'loads' the JSON data.
The problem is, the value returned of readJSON(myURL: path) is equal to nil.
How would I read and write JSON data using SwiftyJSON on ios 10.2?
Update
I have executed my application in the iPhone 6s simulator and checked the saved file json.json. Here is the saved file:
{"array":[12.34,56.78],"users":[{"id":987654,"info":{"name":"jack","email":"jack#gmail.com"},"feeds":[98833,23443,213239,23232]},{"id":654321,"info":{"name":"jeffgukang","email":"jeffgukang#gmail.com"},"feeds":[12345,56789,12423,12412]}]}
I have just relised what the problem was.
In the readJSON() function:
func readJSON(myURL:URL) throws -> JSON? {
if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
{
let path = dir.appendingPathComponent(jsonFile)
if(!FileManager.default.fileExists(atPath: path.path))
{
let data = try Data(contentsOf: path, options: .alwaysMapped)
return JSON(data: data)
}
}
return nil
}
the line if(!FileManager.default.fileExists(atPath: path.path)) should have been if(FileManager.default.fileExists(atPath: path.path)).
Before, I was only loading the data if the file did not exist.

How to parse this specific JSON data in Swift 2.0

I'm trying to parse Json Data from an API :
{
"title": "Mr. Robot",
"first_aired": "2015-06-24",
"network": "USA Network",
"channels": [
{
"id": 12,
"name": "USA",
"short_name": "usa",
"channel_type": "television"
}
],
The Code I'm use is:
var TVArray : [TVInfo] = []
var task : NSURLSessionTask?
func getJSON (urlString: String) {
let url = NSURL(string: urlString)!
let session = NSURLSession.sharedSession()
task = session.dataTaskWithURL(url) {(data, response, error) in
dispatch_async(dispatch_get_main_queue()) {
if (error == nil) {
self.updateJSON(data)
}
else {
}
}
}
task!.resume()
}
func updateJSON (data: NSData!) {
let JSONData = (try! NSJSONSerialization.JSONObjectWithData(data, options: []))
TVArray.removeAll(keepCapacity: true)
if let jsonArray = JSONData {
for j in jsonArray {
let title = jsonResult["title"] as! String
let firstAired = jsonResult["first_aired"] as! String
let network = jsonResult["network"] as! String
let channelName = JsonResult["channels"][0]["name"] as! String
let TV = TVInfo(title: title, firstAired: firstAired, network: network, channelName: channelName)
TVArray.append(TV)
}
}
collectionview.reloadData()
}
}
When I use the above code I get an error 'Initializer for conditional binding must have Optional type, not 'AnyObject'' in front of the line 'if let jsonArray = JsonData'. I've tried some methods I've seen on StackOverflow like the method in the link :
[Parsing JSON in swift 2.0
but it didn't work for me. I'm still a bit new to Swift, I really don't want to use SwiftyJSON. Is this the best way to parse this JSON data or is there a better way of doing it?
Since you've used NSJSONSerialization with try! (note the !, meaning it was forced) the value of JSONData is not an optional: you don't have to unwrap it with if let jsonArray = JSONData.
If you still want an optional value, use try? instead.
Otherwise you could also use try inside a do catch block to handle possible errors.
The type of JSONData is unknown, it needs to be known to be an Array for the following for loop.
use:
let JSONData = try! NSJSONSerialization.JSONObjectWithData(data!, options:[]) as! NSArray
You do not need:
if let jsonArray = JSONData {
because you have already crashed if JSONData is nil from the preceding try!
You are better with:
do {
let jsonArray = try NSJSONSerialization.JSONObjectWithData(data!, options:[]) as! NSArray
for j in jsonArray {
// ...
}
} catch {
// handle error
}
Because you have no control over the JSON you receive and crashing because of a server change is not a good idea.
Also really put some time into naming variables, JSONData is not data, it is an array obtained by parsing a JSON string.