【问题标题】:Simple and clean way to convert JSON string to Object in Swift在 Swift 中将 JSON 字符串转换为 Object 的简单而干净的方法
【发布时间】:2014-10-26 14:02:00
【问题描述】:

我一直在寻找几天来将一个相当简单的 JSON 字符串转换为 Swift 中的对象类型,但无济于事。

这里是网络服务调用的代码:

func GetAllBusiness() {

        Alamofire.request(.GET, "http://MyWebService/").responseString { (request, response, string, error) in

                println(string)

        }
}

我有一个 swift 结构 Business.swift:

struct Business {
    var Id : Int = 0
    var Name = ""
    var Latitude = ""
    var Longitude = ""
    var Address = ""
}

这是我部署的测试服务:

[
  {
    "Id": 1,
    "Name": "A",
    "Latitude": "-35.243256",
    "Longitude": "149.110701",
    "Address": null
  },
  {
    "Id": 2,
    "Name": "B",
    "Latitude": "-35.240592",
    "Longitude": "149.104843",
    "Address": null
  }
  ...
]

如果有人指导我完成这将是一种乐趣。

谢谢。

【问题讨论】:

    标签: ios json swift iphone


    【解决方案1】:

    以下是一些如何从简单示例开始的技巧。

    假设您有以下 JSON 数组字符串(类似于您的),例如:

     var list:Array<Business> = []
    
      // left only 2 fields for demo
      struct Business {
        var id : Int = 0
        var name = ""               
     }
    
     var jsonStringAsArray = "[\n" +
            "{\n" +
            "\"id\":72,\n" +
            "\"name\":\"Batata Cremosa\",\n" +            
            "},\n" +
            "{\n" +
            "\"id\":183,\n" +
            "\"name\":\"Caldeirada de Peixes\",\n" +            
            "},\n" +
            "{\n" +
            "\"id\":76,\n" +
            "\"name\":\"Batata com Cebola e Ervas\",\n" +            
            "},\n" +
            "{\n" +
            "\"id\":56,\n" +
            "\"name\":\"Arroz de forma\",\n" +            
        "}]"
    
    
            // convert String to NSData
            var data: NSData = jsonStringAsArray.dataUsingEncoding(NSUTF8StringEncoding)!
            var error: NSError?
    
            // convert NSData to 'AnyObject'
            let anyObj: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(0),
                error: &error)
            println("Error: \(error)")
    
         // convert 'AnyObject' to Array<Business>
         list = self.parseJson(anyObj!)
    
         //===============
    
        func parseJson(anyObj:AnyObject) -> Array<Business>{
    
            var list:Array<Business> = []
    
             if  anyObj is Array<AnyObject> {
    
                var b:Business = Business()
    
                for json in anyObj as Array<AnyObject>{
                 b.name = (json["name"] as AnyObject? as? String) ?? "" // to get rid of null
                 b.id  =  (json["id"]  as AnyObject? as? Int) ?? 0                 
    
                   list.append(b)
                }// for
    
            } // if
    
          return list
    
        }//func    
    

    [编辑]

    去掉null改为:

    b.name = (json["name"] as AnyObject? as? String) ?? ""
    b.id  =  (json["id"]  as AnyObject? as? Int) ?? 0 
    

    另请参阅Coalescing Operator(又名??)的参考

    希望它能帮助你解决问题,

    【讨论】:

    • 太棒了!像魅力一样工作。谢谢!只是一件小事,如果 JSON 中的元素为空,则会出错。就像:b.name = json["name"] as AnyObject! as String 如果名称为空,如何添加条件使其可以为空?
    • 在转换为 String 之前需要转换为 AnyObject 吗?
    • @Bateramos 什么都没有。您可以通过键获得可选的AnyObject,只需在向下转换为字符串之前确定它不是nil。出于这个原因,我可以使用! 或在我的情况下使用? 和holdplace ?? 来封装。
    • 我猜,如果您在侧循环之外创建对象var b:Business = Business(),那么它可能会在每个列表元素中显示相同的数据。
    • 简单干净的方式 =))))
    【解决方案2】:

    我编写了一个库,它使在 Swift 中处理 json 数据和反序列化变得轻而易举。你可以在这里得到它:https://github.com/isair/JSONHelper

    编辑:我更新了我的库,您现在可以这样做:

    class Business: Deserializable {
        var id: Int?
        var name = "N/A"  // This one has a default value.
    
        required init(data: [String: AnyObject]) {
            id <-- data["id"]
            name <-- data["name"]
        }
    }
    
    var businesses: [Business]()
    
    Alamofire.request(.GET, "http://MyWebService/").responseString { (request, response, string, error) in
        businesses <-- string
    }
    

    旧答案:

    首先,使用 .response 来获取响应对象,而不是使用 .responseString。然后将您的代码更改为:

    func getAllBusinesses() {
    
        Alamofire.request(.GET, "http://MyWebService/").response { (request, response, data, error) in
            var businesses: [Business]?
    
            businesses <-- data
    
            if businesses == nil {
                // Data was not structured as expected and deserialization failed, do something.
            } else {
                // Do something with your businesses array. 
            }
        }
    }
    

    你需要像这样制作一个商务舱:

    class Business: Deserializable {
        var id: Int?
        var name = "N/A"  // This one has a default value.
    
        required init(data: [String: AnyObject]) {
            id <-- data["id"]
            name <-- data["name"]
        }
    }
    

    您可以在我的 GitHub 存储库中找到完整的文档。玩得开心!

    【讨论】:

    • 谢谢!但我更多的是在寻找一种自定义的方式来做这件事,因为这是我正在从事的一个大学项目,如果我的主管看到我正在使用 API,他不会很高兴。
    • 将在我的私人项目中使用您的库。谢谢!!
    • 很高兴我能够以某种方式提供帮助。祝你的项目好运! ^^
    【解决方案3】:

    简单的字符串扩展就足够了:

    extension String {
    
        var parseJSONString: AnyObject? {
    
            let data = self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
    
            if let jsonData = data {
                // Will return an object or nil if JSON decoding fails
                return NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers, error: nil)
            } else {
                // Lossless conversion of the string was not possible
                return nil
            }
        }
    }
    

    然后:

    var jsonString = "[\n" +
        "{\n" +
        "\"id\":72,\n" +
        "\"name\":\"Batata Cremosa\",\n" +            
        "},\n" +
        "{\n" +
        "\"id\":183,\n" +
        "\"name\":\"Caldeirada de Peixes\",\n" +            
        "},\n" +
        "{\n" +
        "\"id\":76,\n" +
        "\"name\":\"Batata com Cebola e Ervas\",\n" +            
        "},\n" +
        "{\n" +
        "\"id\":56,\n" +
        "\"name\":\"Arroz de forma\",\n" +            
    "}]"
    
    let json: AnyObject? = jsonString.parseJSONString
    println("Parsed JSON: \(json!)")
    println("json[3]: \(json![3])")
    
    /* Output:
    
    Parsed JSON: (
        {
        id = 72;
        name = "Batata Cremosa";
        },
        {
        id = 183;
        name = "Caldeirada de Peixes";
        },
        {
        id = 76;
        name = "Batata com Cebola e Ervas";
        },
        {
        id = 56;
        name = "Arroz de forma";
        }
    )
    
    json[3]: {
        id = 56;
        name = "Arroz de forma";
    }
    */
    

    【讨论】:

      【解决方案4】:
      let jsonString = "{\"id\":123,\"Name\":\"Munish\"}"
      

      将字符串转换为 NSData

       var data: NSData =jsonString.dataUsingEncoding(NSUTF8StringEncoding)!
      
       var error: NSError?
      

      将 NSData 转换为 AnyObject

      var jsonObject: AnyObject? = NSJSONSerialization.JSONObjectWithData(data,     options: NSJSONReadingOptions.allZeros, error: &error)
      
      println("Error: \\(error)")
      
      let id = (jsonObject as! NSDictionary)["id"] as! Int
      
      let name = (jsonObject as! NSDictionary)["name"] as! String
      
      println("Id: \\(id)")
      
      println("Name: \\(name)")
      

      【讨论】:

        【解决方案5】:

        对于 Swift 4

        我使用了@Passkit 的逻辑,但我必须按照 Swift 4 进行更新


        Step.1 为字符串类创建扩展

        import UIKit
        
        
        extension String
            {
                var parseJSONString: AnyObject?
                {
                    let data = self.data(using: String.Encoding.utf8, allowLossyConversion: false)
        
                    if let jsonData = data
                    {
                        // Will return an object or nil if JSON decoding fails
                        do
                        {
                            let message = try JSONSerialization.jsonObject(with: jsonData, options:.mutableContainers)
                            if let jsonResult = message as? NSMutableArray
                            {
                                print(jsonResult)
        
                                return jsonResult //Will return the json array output
                            }
                            else
                            {
                                return nil
                            }
                        }
                        catch let error as NSError
                        {
                            print("An error occurred: \(error)")
                            return nil
                        }
                    }
                    else
                    {
                        // Lossless conversion of the string was not possible
                        return nil
                    }
                }
            }
        

        Step.2 这是我在视图控制器中使用的方式

        var jsonString = "[\n" +
            "{\n" +
            "\"id\":72,\n" +
            "\"name\":\"Batata Cremosa\",\n" +            
            "},\n" +
            "{\n" +
            "\"id\":183,\n" +
            "\"name\":\"Caldeirada de Peixes\",\n" +            
            "},\n" +
            "{\n" +
            "\"id\":76,\n" +
            "\"name\":\"Batata com Cebola e Ervas\",\n" +            
            "},\n" +
            "{\n" +
            "\"id\":56,\n" +
            "\"name\":\"Arroz de forma\",\n" +            
        "}]"
        
         //Convert jsonString to jsonArray
        
        let json: AnyObject? = jsonString.parseJSONString
        print("Parsed JSON: \(json!)")
        print("json[2]: \(json![2])")
        

        所有功劳归原始用户所有,我刚刚更新了最新的 swift 版本

        【讨论】:

          【解决方案6】:

          我喜欢 RDC 的响应,但为什么将返回的 JSON 限制为只有顶级数组?我需要在顶层允许字典,所以我修改了它:

          extension String
          {
              var parseJSONString: AnyObject?
              {
                  let data = self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
          
                  if let jsonData = data
                  {
                      // Will return an object or nil if JSON decoding fails
                      do
                      {
                          let message = try NSJSONSerialization.JSONObjectWithData(jsonData, options:.MutableContainers)
                          if let jsonResult = message as? NSMutableArray {
                              return jsonResult //Will return the json array output
                          } else if let jsonResult = message as? NSMutableDictionary {
                              return jsonResult //Will return the json dictionary output
                          } else {
                              return nil
                          }
                      }
                      catch let error as NSError
                      {
                          print("An error occurred: \(error)")
                          return nil
                      }
                  }
                  else
                  {
                      // Lossless conversion of the string was not possible
                      return nil
                  }
              }
          

          【讨论】:

            【解决方案7】:

            为 Swift 3/4

            extension String {
                func toJSON() -> Any? {
                    guard let data = self.data(using: .utf8, allowLossyConversion: false) else { return nil }
                    return try? JSONSerialization.jsonObject(with: data, options: .mutableContainers)
                }
            }
            

            示例用法:

             let dict = myString.toJSON() as? [String:AnyObject] // can be any type here
            

            【讨论】:

            • 未来的脚注:这里可以使用try? 代替do-catch,这与在catch 中返回nil 的结果相同。
            • ...以及在此转换之后如何访问参数?
            • 对于其他感兴趣的人:让 jsonObjectAsNSDictionary = responseString?.toJSON() as! [String:AnyObject] print(jsonObjectAsNSDictionary["permissions"]!["canadditowncomment"])
            • 请更正swift语法...extension String { func toJSON() -&gt; Any? { guard let data = self.data(using: .utf8, allowLossyConversion: false) else { return nil } return try? JSONSerialization.jsonObject(with: data, options: .mutableContainers) } }
            【解决方案8】:

            对于iOS 10 & Swift 3,使用Alamofire & Gloss

            Alamofire.request("http://localhost:8080/category/en").responseJSON { response in
            
            if let data = response.data {
            
                if let categories = [Category].from(data: response.data) {
            
                    self.categories = categories
            
                    self.categoryCollectionView.reloadData()
                } else {
            
                    print("Casting error")
                }
              } else {
            
                print("Data is null")
              }
            }
            

            这里是 Category 类

            import Gloss
            
            struct Category: Decodable {
            
                let categoryId: Int?
                let name: String?
                let image: String?
            
                init?(json: JSON) {
                    self.categoryId = "categoryId" <~~ json
                    self.name = "name" <~~ json
                    self.image = "image" <~~ json
                }
            }
            

            IMO,这是迄今为止最优雅的解决方案。

            【讨论】:

            • 将 Gloss 替换为 Codable,因为 Gloss 已存档(支持 Swift 的 Codable 框架)
            【解决方案9】:

            您可以使用swift.quicktype.ioJSON 转换为structclass。甚至你可以提到 swift 的版本来生成代码。

            示例 JSON:

            {
              "message": "Hello, World!"
            }
            

            生成的代码:

            import Foundation
            
            typealias Sample = OtherSample
            
            struct OtherSample: Codable {
                let message: String
            }
            
            // Serialization extensions
            
            extension OtherSample {
                static func from(json: String, using encoding: String.Encoding = .utf8) -> OtherSample? {
                    guard let data = json.data(using: encoding) else { return nil }
                    return OtherSample.from(data: data)
                }
            
                static func from(data: Data) -> OtherSample? {
                    let decoder = JSONDecoder()
                    return try? decoder.decode(OtherSample.self, from: data)
                }
            
                var jsonData: Data? {
                    let encoder = JSONEncoder()
                    return try? encoder.encode(self)
                }
            
                var jsonString: String? {
                    guard let data = self.jsonData else { return nil }
                    return String(data: data, encoding: .utf8)
                }
            }
            
            extension OtherSample {
                enum CodingKeys: String, CodingKey {
                    case message
                }
            }
            

            【讨论】:

              【解决方案10】:

              Swift 4 更优雅地解析 JSON。只需按照这个简化的示例为您的结构采用可编码协议:

              struct Business: Codable {
                  let id: Int
                  let name: String
              }
              

              要解析 JSON 数组,你告诉解码器数据数组的对象是什么

              let parsedData = decoder.decode([Business].self, from: data)
              

              这是一个完整的工作示例:

              import Foundation
              
              struct Business: Codable {
                  let id: Int
                  let name: String
              }
              
              // Generating the example JSON data: 
              let originalObjects = [Business(id: 0, name: "A"), Business(id: 1, name: "B")]
              let encoder = JSONEncoder()
              let data = try! encoder.encode(originalObjects)
              
              // Parsing the data: 
              let decoder = JSONDecoder()
              let parsedData = try! decoder.decode([Business].self, from: data)
              

              更多背景信息,请查看this excellent guide

              【讨论】:

              • 这样做的缺点是必须跟踪结构,如果您有大约 30 个或更多参数,管理将变得很麻烦。
              • @Starwave:不确定这是否解决了您的问题,但请注意,您只需在用于解码数据的结构中包含您关心的字段。例如。如果 JSON 的格式为 [{"id": 1, "name: "A", "location": "Warsaw"},] 您仍然可以使用相同的 Business 结构对其进行解码。位置字段将被忽略.
              • 见鬼,我没想到……但是,这里的 parsedData 是什么? NSDictionary?
              • @Starwave:它是一个结构数组,就像原来的问题一样。
              【解决方案11】:

              使用SwiftyJSON 库,你可以让它像

              if let path : String = Bundle.main.path(forResource: "tiles", ofType: "json") {
                  if let data = NSData(contentsOfFile: path) {
                      let optData = try? JSON(data: data as Data)
                      guard let json = optData else {
                          return
                      }
                      for (_, object) in json {
                          let name = object["name"].stringValue
                          print(name)
                      }
                  }
              } 
              

              【讨论】:

                【解决方案12】:

                对于 Swift 4,我使用 Codable 协议编写了​​这个扩展:

                struct Business: Codable {
                    var id: Int
                    var name: String
                }
                
                extension String {
                
                    func parse<D>(to type: D.Type) -> D? where D: Decodable {
                
                        let data: Data = self.data(using: .utf8)!
                
                        let decoder = JSONDecoder()
                
                        do {
                            let _object = try decoder.decode(type, from: data)
                            return _object
                
                        } catch {
                            return nil
                        }
                    }
                }
                
                var jsonString = "[\n" +
                    "{\n" +
                    "\"id\":72,\n" +
                    "\"name\":\"Batata Cremosa\",\n" +
                    "},\n" +
                    "{\n" +
                    "\"id\":183,\n" +
                    "\"name\":\"Caldeirada de Peixes\",\n" +
                    "},\n" +
                    "{\n" +
                    "\"id\":76,\n" +
                    "\"name\":\"Batata com Cebola e Ervas\",\n" +
                    "},\n" +
                    "{\n" +
                    "\"id\":56,\n" +
                    "\"name\":\"Arroz de forma\",\n" +
                "}]"
                
                let businesses = jsonString.parse(to: [Business].self)
                

                【讨论】:

                  【解决方案13】:

                  SWIFT4 - 将 JSON 字符串解码为 Struct 的简单而优雅的方式。

                  第一步 - 使用 .utf8 编码将字符串编码为数据。

                  将您的数据解码为 YourDataStruct。

                  struct YourDataStruct: Codable {
                  
                  let type, id: String
                  
                  init(_ json: String, using encoding: String.Encoding = .utf8) throws {
                      guard let data = json.data(using: encoding) else {
                          throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)
                      }
                      try self.init(data: data)
                  }
                  
                  init(data: Data) throws {
                      self = try JSONDecoder().decode(YourDataStruct.self, from: data)
                  }                                                                      
                  }
                  
                  do { let successResponse = try WSDeleteDialogsResponse(response) }
                  } catch {}
                  

                  【讨论】:

                    【解决方案14】:

                    这里有一个示例,可让您让事情变得更简单、更轻松。我的数据库中的字符串数据是一个 JSON 文件,如下所示:

                    [{"stype":"noun","sdsc":"careless disregard for consequences","swds":"disregard, freedom, impulse, licentiousness, recklessness, spontaneity, thoughtlessness, uninhibitedness, unrestraint, wantonness, wildness","anwds":"restraint, self-restraint"},{"stype":"verb","sdsc":"leave behind, relinquish","swds":"abdicate, back out, bail out, bow out, chicken out, cop out, cut loose, desert, discard, discontinue, ditch, drop, drop out, duck, dump, dust, flake out, fly the coop, give up the ship, kiss goodbye, leave, leg it, let go, opt out, pull out, quit, run out on, screw, ship out, stop, storm out, surrender, take a powder, take a walk, throw over, vacate, walk out on, wash hands of, withdraw, yield","anwds":"adopt, advance, allow, assert, begin, cherish, come, continue, defend, favor, go, hold, keep, maintain, persevere, pursue, remain, retain, start, stay, support, uphold"},{"stype":"verb","sdsc":"leave in troubled state","swds":"back out, desert, disown, forsake, jilt, leave, leave behind, quit, reject, renounce, throw over, walk out on","anwds":"adopt, allow, approve, assert, cherish, come, continue, defend, favor, keep, pursue, retain, stay, support, uphold"}]
                    

                    要加载此 JSON 字符串数据,请执行以下简单步骤。 首先,为我的 MoreData 对象创建一个类,如下所示:

                    class  MoreData {
                    public private(set) var stype : String
                    public private(set) var sdsc : String
                    public private(set) var swds : String
                    public private(set) var anwds : String
                    
                    init( stype : String, sdsc : String, swds : String, anwds : String) {
                    
                        self.stype = stype
                        self.sdsc = sdsc
                        self.swds = swds
                        self.anwds = anwds
                    }}
                    

                    其次,为我的 JSON 字符串创建我的字符串扩展,如下所示:

                    extension  String {
                    func toJSON() -> Any? {
                        guard let data = self.data(using: .utf8, allowLossyConversion: false) else { return nil }
                        return try? JSONSerialization.jsonObject(with: data, options: .mutableContainers)
                    }}
                    

                    第三,创建 My Srevices 类来处理我的字符串数据,如下所示:

                    class Services {
                    static let instance: Services = Services()
                    
                    func loadMoreDataByString(byString: String) -> [MoreData]{
                        var  myVariable = [MoreData]()
                    
                        guard let ListOf = byString.toJSON() as? [[String: AnyObject]] else { return  [] }
                    
                        for object in ListOf {
                            let stype  = object["stype"] as? String ?? ""
                            let sdsc  = object["sdsc"] as? String ?? ""
                             let swds  = object["swds"] as? String ?? ""
                            let anwds  = object["anwds"] as? String ?? ""
                    
                            let myMoreData = MoreData(stype : stype, sdsc : sdsc, swds : swds, anwds : anwds)
                            myVariable.append(myMoreData)
                        }
                        return myVariable
                    }}
                    

                    最后,从 View Controller 调用这个 Function 来加载表格视图中的数据,如下所示:

                        func handlingJsonStringData(){
                        moreData.removeAll(keepingCapacity: false)
                        moreData =  Services.instance.loadMoreDataByString(byString: jsonString)
                        print(self.moreData.count)
                        tableView.reloadData()
                    }
                    

                    【讨论】:

                      【解决方案15】:

                      这可能对某人有所帮助。类似的例子。

                      这是我们用于绑定数据的Codable 类。您可以使用SwiftyJsonAccelerator轻松创建此类

                       class ModelPushNotificationFilesFile: Codable {
                      
                        enum CodingKeys: String, CodingKey {
                          case url
                          case id
                          case fileExtension = "file_extension"
                          case name
                        }
                      
                        var url: String?
                        var id: Int?
                        var fileExtension: String?
                        var name: String?
                      
                        init (url: String?, id: Int?, fileExtension: String?, name: String?) {
                          self.url = url
                          self.id = id
                          self.fileExtension = fileExtension
                          self.name = name
                        }
                      
                        required init(from decoder: Decoder) throws {
                          let container = try decoder.container(keyedBy: CodingKeys.self)
                          url = try container.decodeIfPresent(String.self, forKey: .url)
                          id = try container.decodeIfPresent(Int.self, forKey: .id)
                          fileExtension = try container.decodeIfPresent(String.self, forKey: .fileExtension)
                          name = try container.decodeIfPresent(String.self, forKey: .name)
                        }
                      
                      }
                      

                      这是 Json 字符串

                          let jsonString = "[{\"name\":\"\",\"file_extension\":\"\",\"id\":10684,\"url\":\"https:\\/\\/homepages.cae.wisc.edu\\/~ece533\\/images\\/tulips.png\"},
                      
                      {\"name\":\"\",\"file_extension\":\"\",\"id\":10684,\"url\":\"https:\\/\\/homepages.cae.wisc.edu\\/~ece533\\/images\\/arctichare.png\"},
                      
                      {\"name\":\"\",\"file_extension\":\"\",\"id\":10684,\"url\":\"https:\\/\\/homepages.cae.wisc.edu\\/~ece533\\/images\\/serrano.png\"},
                      
                      {\"name\":\"\",\"file_extension\":\"\",\"id\":10684,\"url\":\"https:\\/\\/homepages.cae.wisc.edu\\/~ece533\\/images\\/peppers.png\"},
                      
                      {\"name\":\"\",\"file_extension\":\"\",\"id\":10684,\"url\":\"https:\\/\\/homepages.cae.wisc.edu\\/~ece533\\/images\\/pool.png\"}]"
                      

                      这里我们转换为 swift 对象。

                         let jsonData = Data(jsonString.utf8)
                      
                              let decoder = JSONDecoder()
                      
                              do {
                                  let fileArray = try decoder.decode([ModelPushNotificationFilesFile].self, from: jsonData)
                                  print(fileArray)
                                  print(fileArray[0].url)
                              } catch {
                                  print(error.localizedDescription)
                              }
                      

                      【讨论】:

                        【解决方案16】:

                        使用 swiftyJson swiftyJson

                        platform :ios, '8.0'
                        use_frameworks!
                        
                        target 'MyApp' do
                        pod 'SwiftyJSON', '~> 4.0'
                        end
                        

                        用法

                        import SwiftyJSON
                        
                        let json = JSON(jsonObject)
                        
                        let id = json["Id"].intValue
                        let name = json["Name"].stringValue
                        let lat = json["Latitude"].stringValue
                        let long = json["Longitude"].stringValue
                        let address = json["Address"].stringValue
                                    
                        print(id)
                        print(name)
                        print(lat)
                        print(long)
                        print(address)
                        

                        【讨论】:

                          【解决方案17】:

                          将 json 包装在多行字符串文字中并尝试像这样解析:

                          import Foundation
                          
                          // MARK: - DemoJSON
                          struct DemoJSON: Codable {
                              let menu: Menu
                          }
                          
                          // MARK: - Menu
                          struct Menu: Codable {
                              let id, value: String
                              let popup: Popup
                          }
                          
                          // MARK: - Popup
                          struct Popup: Codable {
                              let menuitem: [Menuitem]
                          }
                          
                          // MARK: - Menuitem
                          struct Menuitem: Codable {
                              let value, onclick: String
                          }
                          
                          
                          
                          /// Make Network Request
                          typealias RequestCompletionHandler<T: Decodable> = (_ value: T?, _ error: Error?) -> Void
                          
                          
                          func callAPI<T: Decodable>(completionHandler: RequestCompletionHandler<T>) {
                              let data = """
                          {"menu": {
                            "id": "file",
                            "value": "File",
                            "popup": {
                              "menuitem": [
                                {"value": "New", "onclick": "CreateNewDoc()"},
                                {"value": "Open", "onclick": "OpenDoc()"},
                                {"value": "Close", "onclick": "CloseDoc()"}
                              ]
                            }
                          }}
                          """.data(using: .utf8)!
                              do {
                                  let value = try JSONDecoder().decode(T.self, from: data)
                                  completionHandler(value, nil)
                              } catch {
                                  completionHandler(nil, error)
                              }
                          }
                          
                          callAPI { (model: DemoJSON?, error) in
                              if let demoModel = model {
                                  print("Success: \(demoModel)")
                              } else if let error = error {
                                  print("Error: \(error)")
                              }
                          }
                          

                          【讨论】:

                            猜你喜欢
                            • 2015-08-25
                            • 2013-09-16
                            • 2010-12-21
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 2023-03-13
                            相关资源
                            最近更新 更多