Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 592 Vote(s) - 3.55 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Reading in a JSON File Using Swift

#31
For those looking to print the JSON data in the debugger / `lldb` after Decodable has thrown an error try this.

`po try! JSONSerialization.jsonObject(with: data!, options: .mutableLeaves) as? Dictionary<String, Any>`
Reply

#32
I wasted my time in locating file which was located in my project with name `Jsondata.json`. But I weren't able to locate my File through code....

**Solution**: Make sure that your `Jsondata.json` file is added in **Project> Build Phases> Copy Bundle Resources.** Otherwise you wont be able to get file and `Bundle.main.url(forResource: fileName, withExtension: "json")` will give you `nil` always.
Reply

#33
Swift 5 answer worked for me, except that is missing that i must add a empty file, rename it as xxx.json after it works, and using generics.



func loadJson<T:Codable>(filename fileName: String) -> T? {
if let url = Bundle.main.url(forResource: fileName, withExtension: "json") {
do {
let data = try Data(contentsOf: url)
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
} catch {
print("error:\(error)")
}
}
return nil
}

`code`
Reply

#34
For those who is looking for reusable function I made a class that responsible for JSON loading.
```
import Foundation

class JSONLoader {
static func load<T: Decodable>(resource: String, type: T.Type) -> T {
guard let file = Bundle.main.url(forResource: resource, withExtension: nil) else {
fatalError("Couldn't find \(resource) in main bundle.")
}
let data: Data
do {
data = try Data(contentsOf: file)
} catch {
fatalError("Couldn't load \(resource) from main bundle:\n\(error)")
}
do {
return try JSONDecoder().decode(type, from: data)
} catch {
fatalError("Couldn't parse \(resource) as \(T.self):\n\(error)")
}
}

static func load<T: Decodable>(resource: String) -> T {
load(resource: resource, type: T.self)
}
}
// Usage:
let employee1 = JSONLoader.load("employee.json", Employee.self)
let employee2: Employee = JSONLoader.load("employee.json")
```
Reply

#35
A generic approach can be like that:

Create json file with Response class name string

struct Response: Codable,FileDecodable {
typealias T = Self
let names:[Data]
}
protocol FileDecodable{
associatedtype T:Codable
static func loadJson() ->T?
}

extension FileDecodable{
static func loadJson() -> T? {
let fileName = String(describing: T.self)
if let url = Bundle.main.url(forResource: fileName, withExtension: "json") {
do {
let data = try Data(contentsOf: url)
let decoder = JSONDecoder()
let jsonData = try decoder.decode(T.self, from: data)
return jsonData
} catch {
print("error:\(error)")
}
}
return nil
}
}

Reply

#36
## One more answer here??? ##

Ok. Hold on! All of the answers before were about using `JSONSerialization`, or returns nil, or ignores errors.

## What is the different ##

"My solution" (is is not really my, this is a mix of the solutions above) contains:
1. Modern way to return values: `Result<Value,Error>` (returns Value or Error)
2. Avoids `nil` usage
3. Contains a slightly verbose error
4. Uses extension to have pretty/intuitive interface: `Model.from(localJSON: "myJsonFile")`
5. Gives possibility to select bundle

## Details ##

- Xcode 14
- Swift 5.6.1

## Solution 1. JSON file -> Decodable ##

enum JSONParseError: Error {
case fileNotFound
case dataInitialisation(error: Error)
case decoding(error: Error)
}

extension Decodable {
static func from(localJSON filename: String,
bundle: Bundle = .main) -> Result<Self, JSONParseError> {
guard let url = bundle.url(forResource: filename, withExtension: "json") else {
return .failure(.fileNotFound)
}
let data: Data
do {
data = try Data(contentsOf: url)
} catch let error {
return .failure(.dataInitialisation(error: error))
}

do {
return .success(try JSONDecoder().decode(self, from: data))
} catch let error {
return .failure(.decoding(error: error))
}
}
}

## Solution 1 Usage ##

struct Model: Decodable {
let uuid: String
let name: String
}

switch Model.from(localJSON: "myjsonfile") {
case .success(let value):
print(value)
case .failure(let error):
print(error)
}

## Solution 2. JSON file -> Dictionary ##

extension Dictionary where Key == String, Value == Any {

enum JSONParseError: Error {
case fileNotFound(filename: String)
case dataInitialisation(Error)
case jsonSerialization(Error)
case mappingFail(value: Any, toType: Any)
}

static func from(JSONfile url: URL) -> Result<Self, JSONParseError> {
let data: Data
do {
data = try Data(contentsOf: url)
} catch let error {
return .failure(.dataInitialisation(error))
}

let jsonObject: Any
do {
jsonObject = try JSONSerialization.jsonObject(with: data, options: .mutableLeaves)
} catch let error {
return .failure(.jsonSerialization(error))
}

guard let jsonResult = jsonObject as? Self else {
return .failure(.mappingFail(value: jsonObject, toType: Self.Type.self))
}

return .success(jsonResult)
}

static func from(localJSONfile name: String) -> Result<Self, JSONParseError> {
let fileType = "json"
let fullFileName = name + (name.contains(fileType) ? "" : ".\(fileType)")
guard let path = Bundle.main.path(forResource: fullFileName, ofType: "") else {
return .failure(.fileNotFound(filename: fullFileName))
}
return from(JSONfile: URL(fileURLWithPath: path))
}
}

## Solution 2 Usage ##

switch [String: Any].from(localJSONfile: "file.json") {
// OR switch [String: Any].from(localJSONfile: "file.json") {
// OR switch [String: Any].from(JSONfile: url) {
case let .success(dictionary):
print(dictionary)
case let .failure(error):
print("ERROR: \(error)")
}
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through