使用Swift读取JSON文件

我真的在努力把一个JSON文件读入Swift,这样我就可以玩它了。我花了2天的时间重新搜索和尝试不同的方法,但没有运气,所以我已经注册了StackOverFlow,看看是否有人能给我指点正确的方向.....

我的JSON文件叫做test。Json,并包含以下内容:

{
"person":[
{
"name": "Bob",
"age": "16",
"employed": "No"
},
{
"name": "Vinny",
"age": "56",
"employed": "Yes"
}
]
}

该文件直接存储在文档中,我使用以下代码访问它:

let file = "test.json"
let dirs : String[] = NSSearchPathForDirectoriesInDomains(
NSSearchpathDirectory.DocumentDirectory,
NSSearchPathDomainMask.AllDomainMask,
true) as String[]


if (dirs != nil) {
let directories: String[] = dirs
let dir = directories[0]
let path = dir.stringByAppendingPathComponent(file)
}


var jsonData = NSData(contentsOfFile:path, options: nil, error: nil)
println("jsonData \(jsonData)" // This prints what looks to be JSON encoded data.


var jsonDict = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: nil) as? NSDictionary


println("jsonDict \(jsonDict)") - This prints nil.....

如果有人能给我一个正确的方向,我可以反序列化JSON文件,并把它放在一个可访问的Swift对象,我会永远感激!

亲切的问候,

Krivvenz。

326456 次浏览

遵循以下代码:

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
}
}
}
}

数组“persons”将包含关键人物的所有数据。遍历获取它。

斯威夫特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
}
}

如果有人在寻找SwiftyJSON答案:
更新: < br > Swift 3/4: < / p >

if let path = Bundle.main.path(forResource: "assets/test", ofType: "json") {
do {
let data = try Data(contentsOf: URL(fileURLWithPath: path), options: .alwaysMapped)
let jsonObj = try JSON(data: data)
print("jsonData:\(jsonObj)")
} catch let error {
print("parse error: \(error.localizedDescription)")
}
} else {
print("Invalid filename/path.")
}

这对我很有效

func readjson(fileName: String) -> NSData{


let path = NSBundle.mainBundle().pathForResource(fileName, ofType: "json")
let jsonData = NSData(contentsOfMappedFile: path!)


return jsonData!
}

我提供了另一个答案,因为这里没有一个答案是针对从测试包加载资源的。如果您正在使用一个输出JSON的远程服务,并且希望在不触及实际服务的情况下对解析结果进行单元测试,则可以获取一个或多个响应,并将它们放入项目中的Tests文件夹中的文件中。

func testCanReadTestJSONFile() {
let path = NSBundle(forClass: ForecastIOAdapterTests.self).pathForResource("ForecastIOSample", ofType: "json")
if let jsonData = NSData(contentsOfFile:path!) {
let json = JSON(data: jsonData)
if let currentTemperature = json["currently"]["temperature"].double {
println("json: \(json)")
XCTAssertGreaterThan(currentTemperature, 0)
}
}
}

这也使用SwiftyJSON,但获得测试包和加载文件的核心逻辑是问题的答案。

下面是我使用SwiftyJSON的解决方案

if let path : String = NSBundle.mainBundle().pathForResource("filename", ofType: "json") {
if let data = NSData(contentsOfFile: path) {


let json = JSON(data: data)


}
}

基于阿布舍克的回答,对于iOS 8,这将是:

let masterDataUrl: NSURL = NSBundle.mainBundle().URLForResource("masterdata", withExtension: "json")!
let jsonData: NSData = NSData(contentsOfURL: masterDataUrl)!
let jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: nil) as! NSDictionary
var persons : NSArray = jsonResult["person"] as! NSArray

Swift 2.1答案(基于Abhishek):

    if let path = NSBundle.mainBundle().pathForResource("test", ofType: "json") {
do {
let jsonData = try NSData(contentsOfFile: path, options: NSDataReadingOptions.DataReadingMappedIfSafe)
do {
let jsonResult: NSDictionary = try NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
if let people : [NSDictionary] = jsonResult["person"] as? [NSDictionary] {
for person: NSDictionary in people {
for (name,value) in person {
print("\(name) , \(value)")
}
}
}
} catch {}
} catch {}
}

斯威夫特4。X和5。x使用可解码

struct ResponseData: Decodable {
var person: [Person]
}
struct Person : Decodable {
var name: String
var age: String
var employed: String
}


func loadJson(filename fileName: String) -> [Person]? {
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(ResponseData.self, from: data)
return jsonData.person
} catch {
print("error:\(error)")
}
}
return nil
}

斯威夫特3

func loadJson(filename fileName: String) -> [String: AnyObject]? {
if let url = Bundle.main.url(forResource: fileName, withExtension: "json") {
do {
let data = try Data(contentsOf: url)
let object = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
if let dictionary = object as? [String: AnyObject] {
return dictionary
}
} catch {
print("Error!! Unable to parse  \(fileName).json")
}
}
return nil
}

我已经使用下面的代码获取JSON从FAQ-data。Json文件存在于项目目录中。

我在Xcode 7.3中使用Swift实现。

     func fetchJSONContent() {
if let path = NSBundle.mainBundle().pathForResource("FAQ-data", ofType: "json") {


if let jsonData = NSData(contentsOfFile: path) {
do {
if let jsonResult: NSDictionary = try NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary {


if let responseParameter : NSDictionary = jsonResult["responseParameter"] as? NSDictionary {


if let response : NSArray = responseParameter["FAQ"] as? NSArray {
responseFAQ = response
print("response FAQ : \(response)")
}
}
}
}
catch { print("Error while parsing: \(error)") }
}
}
}


override func viewWillAppear(animated: Bool) {
fetchFAQContent()
}

JSON文件结构:

{
"status": "00",
"msg": "FAQ List ",
"responseParameter": {
"FAQ": [
{
"question": “Question No.1 here”,
"answer": “Answer goes here”,
"id": 1
},
{
"question": “Question No.2 here”,
"answer": “Answer goes here”,
"id": 2
}
. . .
]
}
}

我可能还会推荐Ray Wenderlich的Swift JSON教程(它也涵盖了很棒的SwiftyJSON替代品光泽)。一段摘录(它本身并不能完全回答海报上的问题,但这个答案的附加价值是链接,所以请不要给它加-1):

在Objective-C中,解析和反序列化JSON相当简单:

NSArray *json = [NSJSONSerialization JSONObjectWithData:JSONData
options:kNilOptions error:nil];
NSString *age = json[0][@"person"][@"age"];
NSLog(@"Dani's age is %@", age);

在Swift中,由于Swift的可选选项和类型安全,解析和反序列化JSON有点繁琐,但作为Swift 2.0的一部分,guard语句被引入,以帮助摆脱嵌套的if语句:

var json: Array!
do {
json = try NSJSONSerialization.JSONObjectWithData(JSONData, options: NSJSONReadingOptions()) as? Array
} catch {
print(error)
}


guard let item = json[0] as? [String: AnyObject],
let person = item["person"] as? [String: AnyObject],
let age = person["age"] as? Int else {
return;
}
print("Dani's age is \(age)")

当然,在XCode 8中。x,你只需双击空格键,然后说“嘿,Siri,请在Swift 3.0中用空格/制表符缩进为我反序列化这个JSON。”

Swift 3.0的更新名称

基于阿布舍克的回答Druva的回答

func loadJson(forFilename fileName: String) -> NSDictionary? {


if let url = Bundle.main.url(forResource: fileName, withExtension: "json") {
if let data = NSData(contentsOf: url) {
do {
let dictionary = try JSONSerialization.jsonObject(with: data as Data, options: .allowFragments) as? NSDictionary


return dictionary
} catch {
print("Error!! Unable to parse  \(fileName).json")
}
}
print("Error!! Unable to load  \(fileName).json")
}


return nil
}

Xcode 8 Swift 3读取json文件更新:

    if let path = Bundle.main.path(forResource: "userDatabseFakeData", ofType: "json") {
do {
let jsonData = try NSData(contentsOfFile: path, options: NSData.ReadingOptions.mappedIfSafe)
do {
let jsonResult: NSDictionary = try JSONSerialization.jsonObject(with: jsonData as Data, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSDictionary
if let people : [NSDictionary] = jsonResult["person"] as? [NSDictionary] {
for person: NSDictionary in people {
for (name,value) in person {
print("\(name) , \(value)")
}
}
}
} catch {}
} catch {}
}

Swift 3.0, Xcode 8, iOS 10

 if let path = Bundle.main.url(forResource: "person", withExtension: "json") {


do {
let jsonData = try Data(contentsOf: path, options: .mappedIfSafe)
do {
if let jsonResult = try JSONSerialization.jsonObject(with: jsonData, options: JSONSerialization.ReadingOptions(rawValue: 0)) as? NSDictionary {
if let personArray = jsonResult.value(forKey: "person") as? NSArray {
for (_, element) in personArray.enumerated() {
if let element = element as? NSDictionary {
let name = element.value(forKey: "name") as! String
let age = element.value(forKey: "age") as! String
let employed = element.value(forKey: "employed") as! String
print("Name: \(name),  age: \(age), employed: \(employed)")
}
}
}
}
} catch let error as NSError {
print("Error: \(error)")
}
} catch let error as NSError {
print("Error: \(error)")
}
}

输出:< em > < / em >

Name: Bob,  age: 16, employed: No
Name: Vinny,  age: 56, employed: Yes

最新的swift 3.0绝对有效

func loadJson(filename fileName: String) -> [String: AnyObject]?
{
if let url = Bundle.main.url(forResource: fileName, withExtension: "json")
{
if let data = NSData(contentsOf: url) {
do {
let object = try JSONSerialization.jsonObject(with: data as Data, options: .allowFragments)
if let dictionary = object as? [String: AnyObject] {
return dictionary
}
} catch {
print("Error!! Unable to parse  \(fileName).json")
}
}
print("Error!! Unable to load  \(fileName).json")
}
return nil
}

Swiftyjson版本swift 3

func loadJson(fileName: String) -> JSON {


var dataPath:JSON!


if let path : String = Bundle.main.path(forResource: fileName, ofType: "json") {
if let data = NSData(contentsOfFile: path) {
dataPath = JSON(data: data as Data)
}
}
return dataPath
}
fileprivate class BundleTargetingClass {}
func loadJSON<T>(name: String) -> T? {
guard let filePath = Bundle(for: BundleTargetingClass.self).url(forResource: name, withExtension: "json") else {
return nil
}


guard let jsonData = try? Data(contentsOf: filePath, options: .mappedIfSafe) else {
return nil
}


guard let json = try? JSONSerialization.jsonObject(with: jsonData, options: .allowFragments) else {
return nil
}


return json as? T
}

👆🏻复制粘贴就绪,第三方框架独立解决方案。

使用👇🏻

let json:[[String : AnyObject]] = loadJSON(name: "Stations")!

Swift 3更新与最安全的方式

    private func readLocalJsonFile() {


if let urlPath = Bundle.main.url(forResource: "test", withExtension: "json") {


do {
let jsonData = try Data(contentsOf: urlPath, options: .mappedIfSafe)


if let jsonDict = try JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers) as? [String: AnyObject] {


if let personArray = jsonDict["person"] as? [[String: AnyObject]] {


for personDict in personArray {


for (key, value) in personDict {


print(key, value)
}
print("\n")
}
}
}
}


catch let jsonError {
print(jsonError)
}
}
}

enter image description here

这在XCode 8.3.3中是可行的

func fetchPersons(){


if let pathURL = Bundle.main.url(forResource: "Person", withExtension: "json"){


do {


let jsonData = try Data(contentsOf: pathURL, options: .mappedIfSafe)


let jsonResult = try JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers) as! [String: Any]
if let persons = jsonResult["person"] as? [Any]{


print(persons)
}


}catch(let error){
print (error.localizedDescription)
}
}
}

Swift 4.1更新了Xcode 9.2

if let filePath = Bundle.main.path(forResource: "fileName", ofType: "json"), let data = NSData(contentsOfFile: filePath) {


do {
let json = try JSONSerialization.jsonObject(with: data as Data, options: JSONSerialization.ReadingOptions.allowFragments)
}
catch {
//Handle error
}
}

首先像这样创建一个可编码的Struc:

  struct JuzgadosList : Codable {
var CP : Int
var TEL : String
var LOCAL : String
var ORGANO : String
var DIR : String
}

现在声明变量

 var jzdosList = [JuzgadosList]()

从主目录读取

func getJsonFromDirectory() {


if let path = Bundle.main.path(forResource: "juzgados", ofType: "json") {
do {
let data = try Data(contentsOf: URL(fileURLWithPath: path), options: .alwaysMapped)
let jList = try JSONDecoder().decode([JuzgadosList].self, from: data)
self.jzdosList = jList


DispatchQueue.main.async() { () -> Void in
self.tableView.reloadData()
}


} catch let error {
print("parse error: \(error.localizedDescription)")
}
} else {
print("Invalid filename/path.")
}
}

网上阅读

func getJsonFromUrl(){


self.jzdosList.removeAll(keepingCapacity: false)


print("Internet Connection Available!")


guard let url = URL(string: "yourURL")  else { return }


let request = URLRequest(url: url, cachePolicy: URLRequest.CachePolicy.reloadIgnoringLocalCacheData, timeoutInterval: 60.0)
URLSession.shared.dataTask(with: request) { (data, response, err) in
guard let data = data else { return }
do {
let jList = try JSONDecoder().decode([JuzgadosList].self, from: data)
self.jzdosList = jList


DispatchQueue.main.async() { () -> Void in
self.tableView.reloadData()
}
} catch let jsonErr {
print("Error serializing json:", jsonErr)
}
}.resume()
}

试试我的解决方案:

test.json

{
"person":[
{
"name": "Bob",
"age": "16",
"employed": "No"
},
{
"name": "Vinny",
"age": "56",
"employed": "Yes"
}
]
}

RequestCodable.swift

import Foundation


struct RequestCodable:Codable {
let person:[PersonCodable]
}

PersonCodable.swift

import Foundation


struct PersonCodable:Codable {
let name:String
let age:String
let employed:String
}

可解码+ FromJSON.swift

import Foundation


extension Decodable {


static func fromJSON<T:Decodable>(_ fileName: String, fileExtension: String="json", bundle: Bundle = .main) throws -> T {
guard let url = bundle.url(forResource: fileName, withExtension: fileExtension) else {
throw NSError(domain: NSURLErrorDomain, code: NSURLErrorResourceUnavailable)
}


let data = try Data(contentsOf: url)


return try JSONDecoder().decode(T.self, from: data)
}
}

例子:

let result = RequestCodable.fromJSON("test") as RequestCodable?


result?.person.compactMap({ print($0) })


/*
PersonCodable(name: "Bob", age: "16", employed: "No")
PersonCodable(name: "Vinny", age: "56", employed: "Yes")
*/

简化Peter Kreinz提供的例子。适用于Swift 4.2。

扩展函数:

extension Decodable {
static func parse(jsonFile: String) -> Self? {
guard let url = Bundle.main.url(forResource: jsonFile, withExtension: "json"),
let data = try? Data(contentsOf: url),
let output = try? JSONDecoder().decode(self, from: data)
else {
return nil
}


return output
}
}

示例模型:

struct Service: Decodable {
let name: String
}

示例用法:

/// service.json
/// { "name": "Home & Garden" }


guard let output = Service.parse(jsonFile: "service") else {
// do something if parsing failed
return
}


// use output if all good

这个例子也适用于数组:

/// services.json
/// [ { "name": "Home & Garden" } ]


guard let output = [Service].parse(jsonFile: "services") else {
// do something if parsing failed
return
}


// use output if all good

注意,我们没有提供任何不必要的泛型,因此不需要强制转换parse的结果。

Swift 4 JSONClassDecodable -为那些喜欢类

定义类如下:

class People: Decodable {
var person: [Person]?


init(fileName : String){
// url, data and jsonData should not be nil
guard let url = Bundle.main.url(forResource: fileName, withExtension: "json") else { return }
guard let data = try? Data(contentsOf: url) else { return }
guard let jsonData = try? JSONDecoder().decode(People.self, from: data) else { return }


// assigns the value to [person]
person = jsonData.person
}
}


class Person : Decodable {
var name: String
var age: String
var employed: String
}

用法,非常抽象:

let people = People(fileName: "people")
let personArray = people.person

这允许PeoplePerson类的方法,如果需要,变量(属性)和方法也可以标记为private

//change type based on your struct and right JSON file


let quoteData: [DataType] =
load("file.json")


func load<T: Decodable>(_ filename: String, as type: T.Type = T.self) -> T {
let data: Data


guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
else {
fatalError("Couldn't find \(filename) in main bundle.")
}


do {
data = try Data(contentsOf: file)
} catch {
fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
}


do {
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
} catch {
fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}
}




下面的代码适用于我。我正在使用斯威夫特5

let path = Bundle.main.path(forResource: "yourJSONfileName", ofType: "json")
var jsonData = try! String(contentsOfFile: path!).data(using: .utf8)!

然后,如果你的Person结构(或类)是可解码的(以及它的所有属性),你可以简单地做:

let person = try! JSONDecoder().decode(Person.self, from: jsonData)

我避免了所有的错误处理代码,使代码更容易读懂。

Swift 5.1, Xcode 11

你可以用这个:


struct Person : Codable {
let name: String
let lastName: String
let age: Int
}


func loadJson(fileName: String) -> Person? {
let decoder = JSONDecoder()
guard
let url = Bundle.main.url(forResource: fileName, withExtension: "json"),
let data = try? Data(contentsOf: url),
let person = try? decoder.decode(Person.self, from: data)
else {
return nil
}


return person
}

使用这个泛型函数

func readJSONFromFile<T: Decodable>(fileName: String, type: T.Type) -> T? {
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
}

下面这行代码:

let model = readJSONFromFile(fileName: "Model", type: Model.self)

对于这种类型:

struct Model: Codable {
let tall: Int
}

在清理和抛光我的代码之后,我来到了这两个函数,你可以添加到你的项目中,并使用它们非常整洁和快速地从json文件读取数据,并将数据转换为你想要的任何类型!

public func readDataRepresentationFromFile(resource: String, type: String) -> Data? {
let filePath = Bundle.main.path(forResource: resource, ofType: type)
    

if let path = filePath {
let result = FileManager.default.contents(atPath: path)
return result
}
return nil
}

然后在这个函数的帮助下,你可以将你的数据转换为任何你想要的类型:

public func getObject<T: Codable>(of type: T.Type, from file: String) -> T?  {
guard let data = readDataRepresentationFromFile(resource: file, type: "json") else {
return nil
}
if let object = try? JSONDecoder().decode(type, from: data) {
return object
}
return nil
}

应用示例: 在你的代码中调用这个函数,给它你的json文件的名字,这就是你所需要的!< / p >

func getInputDataFromSomeJson(jsonFileName: String) -> YourReqiuredOutputType? {
return getObject(of: YourReqiuredOutputType.self, from: jsonFileName)
}

斯威夫特5 +

用Struct解码jsonData

if let jsonData = readFile(forName: <your file name>) {


do {
let decodedData = try JSONDecoder().decode(<your struct name>.self, from: jsonData)
return decodedData.<what you expect>
} catch { print("JSON decode error") }
}

这将读取文件并返回jsonData

如果你实际上在另一个bundle中(例如test),使用:
let bundlePath = Bundle(for: type(of: self))。path(forResource: name, ofType: "json")

. path(forResource: name, ofType: "json"
private func readFile(forName name: String) -> Data? {
do {


if let bundlePath = Bundle.main.path(forResource: name, ofType: "json"),
let jsonData = try String(contentsOfFile: bundlePath).data(using: .utf8) {
return jsonData
}
} catch {
print(error)
}
return nil
}

对于那些希望在decodeable抛出错误后在调试器/ lldb中打印JSON数据的人,请尝试以下方法。

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

我浪费了我的时间在定位文件,该文件位于我的项目名为Jsondata.json。但是我无法通过代码....找到我的文件

解决方案:确保你的Jsondata.json文件被添加到Project>构建Phases>复制Bundle资源。中,否则你将无法获取文件,而Bundle.main.url(forResource: fileName, withExtension: "json")总是会给你nil

Swift 5的答案为我工作,除了我必须添加一个空文件,重命名为xxx。Json,并使用泛型。

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

这里还有一个答案??

好的。坚持住!之前所有的答案都是关于使用JSONSerialization,或返回nil,或忽略错误。

有什么不同

“我的solution"(是不是真的是我的,这是上面的解决方案的混合)包含:

  1. 返回值的现代方法:Result<Value,Error>(返回值或错误)
  2. 避免使用nil
  3. 包含一个稍微详细的错误
  4. 使用扩展有漂亮/直观的界面:Model.from(localJSON: "myJsonFile")
  5. 提供了选择包的可能性

细节

  • Xcode 14
  • 斯威夫特5.6.1

解决方案1。JSON文件->可解码的

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))
}
}
}

方案一用途

 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)
}

解决方案2。JSON文件->字典

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))
}
}

方案二使用

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)")
}

对于那些正在寻找可重用函数的人,我做了一个负责JSON加载的类。

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")

一般的方法可以是这样的:

创建响应类名称字符串的json文件

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
}
}