How to Parse a Json File in Swift

Reading in a JSON File Using Swift

Follow the below code :

if let path = NSBundle.mainBundle().pathForResource("test", ofType: "json")
{
if let jsonData = NSData(contentsOfFile: path, options: .DataReadingMappedIfSafe, error: nil)
{
if let jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers, error: nil) as? NSDictionary
{
if let persons : NSArray = jsonResult["person"] as? NSArray
{
// Do stuff
}
}
}
}

The array "persons" will contain all data for key person. Iterate throughs to fetch it.

Swift 4.0:

if let path = Bundle.main.path(forResource: "test", 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 person = jsonResult["person"] as? [Any] {
// do stuff
}
} catch {
// handle error
}
}

Parsing data from local JSON file (SWIFT)

First of all lets look into you decoding flow step by step.

Decoding

  1. If you are executing this code directly in your app target, and not in some separate library, for the sake of simplicity you can use Bundle.main to access the path of the json file
guard let path = Bundle.main.path(forResource: "questions", ofType: "json") else {
return
}

  1. To decode the json we want the data to pass it to the decoder, and we can do it without having it converted to string so lets initialise Data directly from url.
let data = try Data(contentsOf: path)

  1. Since we are decoding multiple QnAns objects, the type passed to the decoder needs to be Array of QnAns so we write it like that:
let result = try JSONDecoder().decode([QsAns].self, from: data)

both [QsAns] and Array<QsAns> mean the same


  1. There are many errors that can occur during this flow and do-catch statements make it easy to debug by passing us the exact error that was thrown at us, so lets take advantage of that and print it in the catch closure like so:
catch { print(error) }

Final Flow

With all that in mind we land with a pretty elegant code that is also not very long and reads nicely:

guard let path = Bundle.main.path(forResource: "questions", ofType: "json") else {
return
}
do {
let data = try Data(contentsOf: path)
let result = try JSONDecoder().decode([QsAns].self, from: data)
} catch {
print(error)
}

Cool! Is that all?

Unfortunately your json does not looks like its valid for decoder to read and be able to figure out its contents. To make it work we need to embed the objects into the array.
So instead of:

{ ... }, 
{ ... }

We need

[
{ ... },
{ ... }
]

Ooof!

That should be pretty much it. Let me know how it goes, I will be happy to update the answer if something is not clear of there are still some issues. Good luck!

Bonus Question!

We can easily convert these two arrays into the dictionary by using zip function

// type of dict will be [String: [String]]
let dict = Dictionary(uniqueKeysWithValues: zip(questions, answers))

Parsing JSON file using Swift

Make sure to add What hasn't worked for you and what you have tried? As a New contributor you need to learn how to post questions. Give it a try with my below answer.

Use Codable to parse the JSON like below,

let welcome = try? newJSONDecoder().decode(Welcome.self, from: jsonData)


// Welcome
struct Welcome: Codable {
let team11: Team11

enum CodingKeys: String, CodingKey {
case team11 = "Team11"
}
}

// Team11
struct Team11: Codable {
let results: [String: [Result]]
let tn, division: String
}

// Result
struct Result: Codable {
let g, n: String
}

Note: Your JSON is missing open and ending curly brackets, and I've updated that in your question.

How to parse a JSON file in swift?

This answer was last revised for Swift 5.3 and iOS 14.4 SDK.


Given some already obtained JSON data, you can use JSONDecoder to decode it into your Decodable model (or a collection of models).

let data: Data = /* obtain your JSON data */
let model = try JSONDecoder().decode(Model.self, from: data)

Such model must conform to the Decodable protocol and contain correct mapping between properties and JSON dictionary keys. As an example, consider the following JSON array containing search results of cities beginning with "Wa".

[
{
"id": 123,
"city": "Washington",
"region": "D.C.",
"country": "United States"
},
{
"id": 456,
"city": "Warsaw",
"region": "Mazowieckie",
"country": "Poland"
},
...
]

For that, you need to create a model that contains the correct properties of correct types. If you're using a web API, its documentation will be of great help here.

struct SearchResult: Decodable {
let id: Int
let city: String
let region: String
let country: String
}

Then decode the data with JSONDecoder:

let results = try JSONDecoder().decode([SearchResult].self, from: data)

Given a new array of decoded search results, call one of UITableView's functions to reload its data. Note that the decode function can throw an error which you must somehow handle.

To learn more about decoding custom types in Swift and more advanced usage of the Codable APIs, I recommend checking out this documentation article.

how to parse json data from local files?

Please note that variable JSON in your code is an array of objects.
You have to cast it properly.

func jsonTwo(){
let url = Bundle.main.url(forResource: "car_list", withExtension: "json")!
let data = try! Data(contentsOf: url)
let JSON = try! JSONSerialization.jsonObject(with: data, options: [])
print(".........." , JSON , ".......")
if let jsonArray = JSON as? [[String: Any]] {
for item in jsonArray {
let brand = item["brand"] as? String ?? "No Brand" //A default value
print("=======",brand,"=======")
}
}
}

Parsing a JSON file in Swift

The real problem with your code is the non-existent error handling when decoding, you need to rewrite that part so that it catches and prints any errors

if let data = data {
do {
let Recipes = try Recipe_Decoder.decode(Hit.self, from: data)
completion(Recipes.hits)
}
else {
print(error)
completion(nil)
}
}

If you change to this type of error handling you will get a lot of information from the error which in this case was

keyNotFound(Recipe_Coding_Keys(stringValue: "label", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "hits", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "No value associated with key Recipe_Coding_Keys(stringValue: \"label\", intValue: nil) (\"label\").", underlyingError: nil))

Which tells us that the decoder can't find the key "label" inside "hits" and this is because you are missing one level in your data structure for the key "recipe"

How do I parse JSON file with an array of objects in Swift?

Two points worth mentioning here

  1. The response you are trying to parse should come from https://coronavirus-19-api.herokuapp.com/countries not from https://corona-virus-stats.herokuapp.com/api/v1/cases/general-stats. So use first link instead of second.
        let url = "https://coronavirus-19-api.herokuapp.com/countries"
getData(from: url)

  1. Since there are two fields with null values, mark them optional in your model.
    Sample Image
struct CoronaData: Codable {
let country: String
let cases: Int
let todayCases: Int
let deaths: Int
let todayDeaths: Int
let recovered: Int?
let active: Int?
let critical: Int
let casesPerOneMillion: Int
let deathsPerOneMillion: Int
let totalTests: Int
let testsPerOneMillion: Int
}

How to get data from local JSON file in swift?

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.

How to read local json file based on ID in ios swift?

Your JSON format is correct, just the double quotes you used to wrap keys and values seems wrong. Here is your working JSON:

{
"Telugu_songs": [{
"Id": 1,
"Title": "song1 title",
"Text": "song1 sample text"
},
{
"Id": 2,
"Title": "song2 title",
"Text": "song2 sample text"
},
{
"Id": 3,
"Title": "song3 title",
"Text": "song3 sample text"
}
],

"English_songs": [{
"Id": 1,
"Title": "song1 title",
"Text": "song1 sample text"
},
{
"Id": 2,
"Title": "song2 title",
"Text": "song2 sample text"
},
{
"Id": 3,
"Title": "song3 title",
"Text": "song3 sample text"
}
],

"Hindi_songs": [{
"Id": 1,
"Title": "song1 title",
"Text": "song1 sample text"
},
{
"Id": 2,
"Title": "song2 title",
"Text": "song2 sample text"
},
{
"Id": 3,
"Title": "song3 title",
"Text": "song3 sample text"
}
]
}

UPDATE:

Create a Codable class/struct and then store the JSON data in an array. You can then use increase array index +1, -1 based on your next previous button.



Related Topics



Leave a reply



Submit